From 7e63d4250af36b5b25c30ce843f5d649590e95ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 20 Mar 2026 15:06:26 +0100 Subject: [PATCH 01/69] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20fo?= =?UTF-8?q?r=20ko=20(update-outdated)=20(#15170)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov --- docs/ko/docs/_llm-test.md | 18 +- docs/ko/docs/advanced/additional-responses.md | 4 +- .../docs/advanced/additional-status-codes.md | 2 +- .../ko/docs/advanced/advanced-dependencies.md | 4 +- docs/ko/docs/advanced/async-tests.md | 8 +- docs/ko/docs/advanced/behind-a-proxy.md | 34 ++-- docs/ko/docs/advanced/custom-response.md | 154 +++++++----------- docs/ko/docs/advanced/dataclasses.md | 10 +- docs/ko/docs/advanced/events.md | 6 +- docs/ko/docs/advanced/generate-clients.md | 32 ++-- docs/ko/docs/advanced/index.md | 4 +- docs/ko/docs/advanced/middleware.md | 10 +- docs/ko/docs/advanced/openapi-callbacks.md | 10 +- docs/ko/docs/advanced/openapi-webhooks.md | 2 +- .../path-operation-advanced-configuration.md | 6 +- .../advanced/response-change-status-code.md | 2 +- docs/ko/docs/advanced/response-cookies.md | 6 +- docs/ko/docs/advanced/response-directly.md | 34 +++- docs/ko/docs/advanced/response-headers.md | 6 +- .../docs/advanced/security/http-basic-auth.md | 4 +- docs/ko/docs/advanced/security/index.md | 4 +- .../docs/advanced/security/oauth2-scopes.md | 4 +- docs/ko/docs/advanced/settings.md | 16 +- docs/ko/docs/advanced/sub-applications.md | 34 ++-- docs/ko/docs/advanced/templates.md | 4 +- docs/ko/docs/advanced/testing-websockets.md | 4 +- .../docs/advanced/using-request-directly.md | 4 +- docs/ko/docs/advanced/websockets.md | 24 +-- docs/ko/docs/advanced/wsgi.md | 6 +- docs/ko/docs/alternatives.md | 56 +++---- docs/ko/docs/async.md | 24 +-- docs/ko/docs/benchmarks.md | 2 +- docs/ko/docs/deployment/cloud.md | 8 +- docs/ko/docs/deployment/concepts.md | 8 +- docs/ko/docs/deployment/docker.md | 46 +++--- docs/ko/docs/deployment/fastapicloud.md | 4 +- docs/ko/docs/deployment/https.md | 16 +- docs/ko/docs/deployment/index.md | 2 +- docs/ko/docs/deployment/manually.md | 14 +- docs/ko/docs/deployment/server-workers.md | 6 +- docs/ko/docs/deployment/versions.md | 6 +- docs/ko/docs/environment-variables.md | 10 +- docs/ko/docs/fastapi-cli.md | 71 +++++++- docs/ko/docs/features.md | 26 +-- docs/ko/docs/help-fastapi.md | 58 +++---- docs/ko/docs/history-design-future.md | 14 +- .../authentication-error-status-code.md | 2 +- docs/ko/docs/how-to/conditional-openapi.md | 2 +- docs/ko/docs/how-to/configure-swagger-ui.md | 4 +- docs/ko/docs/how-to/custom-docs-ui-assets.md | 12 +- .../docs/how-to/custom-request-and-route.md | 8 +- docs/ko/docs/how-to/extending-openapi.md | 4 +- docs/ko/docs/how-to/general.md | 22 ++- docs/ko/docs/how-to/graphql.md | 30 ++-- docs/ko/docs/how-to/index.md | 2 +- ...migrate-from-pydantic-v1-to-pydantic-v2.md | 8 +- docs/ko/docs/how-to/testing-database.md | 6 +- docs/ko/docs/index.md | 120 ++++++-------- docs/ko/docs/project-generation.md | 2 +- docs/ko/docs/python-types.md | 10 +- docs/ko/docs/tutorial/background-tasks.md | 8 +- docs/ko/docs/tutorial/bigger-applications.md | 47 +++++- docs/ko/docs/tutorial/body-nested-models.md | 2 +- docs/ko/docs/tutorial/body-updates.md | 6 +- docs/ko/docs/tutorial/body.md | 12 +- docs/ko/docs/tutorial/cors.md | 8 +- docs/ko/docs/tutorial/debugging.md | 2 +- ...pendencies-in-path-operation-decorators.md | 4 +- .../dependencies/dependencies-with-yield.md | 32 ++-- .../dependencies/global-dependencies.md | 6 +- docs/ko/docs/tutorial/dependencies/index.md | 4 +- docs/ko/docs/tutorial/encoder.md | 4 +- docs/ko/docs/tutorial/extra-data-types.md | 4 +- docs/ko/docs/tutorial/extra-models.md | 6 +- docs/ko/docs/tutorial/first-steps.md | 75 +++++++-- docs/ko/docs/tutorial/handling-errors.md | 2 +- docs/ko/docs/tutorial/index.md | 12 +- docs/ko/docs/tutorial/metadata.md | 6 +- docs/ko/docs/tutorial/middleware.md | 14 +- .../tutorial/path-operation-configuration.md | 2 +- .../path-params-numeric-validations.md | 10 +- docs/ko/docs/tutorial/path-params.md | 20 +-- .../tutorial/query-params-str-validations.md | 10 +- docs/ko/docs/tutorial/query-params.md | 2 +- docs/ko/docs/tutorial/request-files.md | 12 +- docs/ko/docs/tutorial/request-form-models.md | 4 +- .../docs/tutorial/request-forms-and-files.md | 8 +- docs/ko/docs/tutorial/request-forms.md | 8 +- docs/ko/docs/tutorial/response-model.md | 9 +- docs/ko/docs/tutorial/response-status-code.md | 8 +- docs/ko/docs/tutorial/schema-extra-example.md | 10 +- docs/ko/docs/tutorial/security/first-steps.md | 10 +- docs/ko/docs/tutorial/security/oauth2-jwt.md | 10 +- .../docs/tutorial/security/simple-oauth2.md | 4 +- docs/ko/docs/tutorial/sql-databases.md | 22 +-- docs/ko/docs/tutorial/static-files.md | 4 +- docs/ko/docs/tutorial/testing.md | 20 +-- docs/ko/docs/virtual-environments.md | 30 ++-- 98 files changed, 812 insertions(+), 704 deletions(-) diff --git a/docs/ko/docs/_llm-test.md b/docs/ko/docs/_llm-test.md index 92bfb83f62..8b7b275c0a 100644 --- a/docs/ko/docs/_llm-test.md +++ b/docs/ko/docs/_llm-test.md @@ -11,7 +11,7 @@ * 번역에서 문제가 없는지 확인합니다. * 필요하다면 언어별 프롬프트, 일반 프롬프트, 또는 영어 문서를 개선합니다. * 그런 다음 번역에서 남아 있는 문제를 수동으로 수정해 좋은 번역이 되게 합니다. -* 좋은 번역을 둔 상태에서 다시 번역합니다. 이상적인 결과는 LLM이 더 이상 번역에 변경을 만들지 않는 것입니다. 이는 일반 프롬프트와 언어별 프롬프트가 가능한 한 최선이라는 뜻입니다(때때로 몇 가지 seemingly random 변경을 할 수 있는데, 그 이유는 LLM은 결정론적 알고리즘이 아니기 때문입니다). +* 좋은 번역을 둔 상태에서 다시 번역합니다. 이상적인 결과는 LLM이 더 이상 번역에 변경을 만들지 않는 것입니다. 이는 일반 프롬프트와 언어별 프롬프트가 가능한 한 최선이라는 뜻입니다(때때로 몇 가지 seemingly random 변경을 할 수 있는데, 그 이유는 [LLM은 결정론적 알고리즘이 아니기 때문](https://doublespeak.chat/#/handbook#deterministic-output)입니다). 테스트: @@ -169,15 +169,15 @@ works(foo="bar") # 이건 동작합니다 🎉 링크 텍스트는 번역되어야 하고, 링크 주소는 변경되지 않아야 합니다: * [위의 제목으로 가는 링크](#code-snippets) -* [내부 링크](index.md#installation){.internal-link target=_blank} -* 외부 링크 -* 스타일로 가는 링크 -* 스크립트로 가는 링크 -* 이미지로 가는 링크 +* [내부 링크](index.md#installation) +* [외부 링크](https://sqlmodel.tiangolo.com/) +* [스타일로 가는 링크](https://fastapi.tiangolo.com/css/styles.css) +* [스크립트로 가는 링크](https://fastapi.tiangolo.com/js/logic.js) +* [이미지로 가는 링크](https://fastapi.tiangolo.com/img/foo.jpg) 링크 텍스트는 번역되어야 하고, 링크 주소는 번역 페이지를 가리켜야 합니다: -* FastAPI 링크 +* [FastAPI 링크](https://fastapi.tiangolo.com/ko/) //// @@ -259,8 +259,8 @@ works(foo="bar") # 이건 동작합니다 🎉 * 여러분 * 여러분의 -* 예: (e.g.) -* 등 (etc.) +* 예: +* 등 * `foo`로서의 `int` * `bar`로서의 `str` diff --git a/docs/ko/docs/advanced/additional-responses.md b/docs/ko/docs/advanced/additional-responses.md index 2ed6bc3fcf..e43d7c727f 100644 --- a/docs/ko/docs/advanced/additional-responses.md +++ b/docs/ko/docs/advanced/additional-responses.md @@ -243,5 +243,5 @@ new_dict = {**old_dict, "new key": "new value"} 응답에 정확히 무엇을 포함할 수 있는지 보려면, OpenAPI 사양의 다음 섹션을 확인하세요: -* OpenAPI Responses Object: `Response Object`를 포함합니다. -* OpenAPI Response Object: `responses` 파라미터 안의 각 응답에 이것의 어떤 항목이든 직접 포함할 수 있습니다. `description`, `headers`, `content`(여기에서 서로 다른 미디어 타입과 JSON Schema를 선언합니다), `links` 등을 포함할 수 있습니다. +* [OpenAPI Responses Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object): `Response Object`를 포함합니다. +* [OpenAPI Response Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object): `responses` 파라미터 안의 각 응답에 이것의 어떤 항목이든 직접 포함할 수 있습니다. `description`, `headers`, `content`(여기에서 서로 다른 미디어 타입과 JSON Schema를 선언합니다), `links` 등을 포함할 수 있습니다. diff --git a/docs/ko/docs/advanced/additional-status-codes.md b/docs/ko/docs/advanced/additional-status-codes.md index e3c898044e..6251b68b23 100644 --- a/docs/ko/docs/advanced/additional-status-codes.md +++ b/docs/ko/docs/advanced/additional-status-codes.md @@ -38,4 +38,4 @@ 추가 상태 코드와 응답을 직접 반환하는 경우, FastAPI는 반환할 내용을 미리 알 수 있는 방법이 없기 때문에 OpenAPI 스키마(API 문서)에 포함되지 않습니다. -하지만 다음을 사용하여 코드에 이를 문서화할 수 있습니다: [추가 응답](additional-responses.md){.internal-link target=_blank}. +하지만 다음을 사용하여 코드에 이를 문서화할 수 있습니다: [추가 응답](additional-responses.md). diff --git a/docs/ko/docs/advanced/advanced-dependencies.md b/docs/ko/docs/advanced/advanced-dependencies.md index eb5d35d957..2755986a21 100644 --- a/docs/ko/docs/advanced/advanced-dependencies.md +++ b/docs/ko/docs/advanced/advanced-dependencies.md @@ -133,7 +133,7 @@ SQLModel(또는 SQLAlchemy)을 사용하면서 이런 특정 사용 사례가 그러면 세션이 데이터베이스 연결을 해제하여, 다른 요청들이 이를 사용할 수 있게 됩니다. -`yield`가 있는 의존성에서 조기 종료가 필요한 다른 사용 사례가 있다면, 여러분의 구체적인 사용 사례와 `yield`가 있는 의존성에 대한 조기 종료가 어떤 점에서 이득이 되는지를 포함해 GitHub Discussions 질문을 생성해 주세요. +`yield`가 있는 의존성에서 조기 종료가 필요한 다른 사용 사례가 있다면, 여러분의 구체적인 사용 사례와 `yield`가 있는 의존성에 대한 조기 종료가 어떤 점에서 이득이 되는지를 포함해 [GitHub Discussions 질문](https://github.com/fastapi/fastapi/discussions/new?category=questions)을 생성해 주세요. `yield`가 있는 의존성에서 조기 종료에 대한 설득력 있는 사용 사례가 있다면, 조기 종료를 선택적으로 활성화할 수 있는 새로운 방법을 추가하는 것을 고려하겠습니다. @@ -145,7 +145,7 @@ FastAPI 0.110.0 이전에는 `yield`가 있는 의존성을 사용한 다음 그 ### 백그라운드 태스크와 `yield`가 있는 의존성, 기술 세부사항 { #background-tasks-and-dependencies-with-yield-technical-details } -FastAPI 0.106.0 이전에는 `yield` 이후에 예외를 발생시키는 것이 불가능했습니다. `yield`가 있는 의존성의 종료 코드는 응답이 전송된 *후에* 실행되었기 때문에, [예외 핸들러](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}가 이미 실행된 뒤였습니다. +FastAPI 0.106.0 이전에는 `yield` 이후에 예외를 발생시키는 것이 불가능했습니다. `yield`가 있는 의존성의 종료 코드는 응답이 전송된 *후에* 실행되었기 때문에, [예외 핸들러](../tutorial/handling-errors.md#install-custom-exception-handlers)가 이미 실행된 뒤였습니다. 이는 주로 백그라운드 태스크 안에서 의존성이 "yield"한 동일한 객체들을 사용할 수 있게 하기 위한 설계였습니다. 백그라운드 태스크가 끝난 뒤에 종료 코드가 실행되었기 때문입니다. diff --git a/docs/ko/docs/advanced/async-tests.md b/docs/ko/docs/advanced/async-tests.md index 0479ac41d1..b477c6c715 100644 --- a/docs/ko/docs/advanced/async-tests.md +++ b/docs/ko/docs/advanced/async-tests.md @@ -16,11 +16,11 @@ `TestClient`는 표준 pytest를 사용하여, 일반 `def` 테스트 함수 안에서 비동기 FastAPI 애플리케이션을 호출하도록 내부에서 마법 같은 처리를 합니다. 하지만 비동기 함수 안에서 이를 사용하면 그 마법은 더 이상 동작하지 않습니다. 테스트를 비동기로 실행하면, 테스트 함수 안에서 `TestClient`를 더 이상 사용할 수 없습니다. -`TestClient`는 HTTPX를 기반으로 하며, 다행히 HTTPX를 직접 사용해 API를 테스트할 수 있습니다. +`TestClient`는 [HTTPX](https://www.python-httpx.org)를 기반으로 하며, 다행히 HTTPX를 직접 사용해 API를 테스트할 수 있습니다. ## 예시 { #example } -간단한 예시로, [더 큰 애플리케이션](../tutorial/bigger-applications.md){.internal-link target=_blank}과 [테스트](../tutorial/testing.md){.internal-link target=_blank}에서 설명한 것과 비슷한 파일 구조를 살펴보겠습니다: +간단한 예시로, [더 큰 애플리케이션](../tutorial/bigger-applications.md)과 [테스트](../tutorial/testing.md)에서 설명한 것과 비슷한 파일 구조를 살펴보겠습니다: ``` . @@ -84,7 +84,7 @@ response = client.get('/') /// warning | 경고 -애플리케이션이 lifespan 이벤트에 의존한다면, `AsyncClient`는 이러한 이벤트를 트리거하지 않습니다. 이벤트가 트리거되도록 하려면 florimondmanca/asgi-lifespan의 `LifespanManager`를 사용하세요. +애플리케이션이 lifespan 이벤트에 의존한다면, `AsyncClient`는 이러한 이벤트를 트리거하지 않습니다. 이벤트가 트리거되도록 하려면 [florimondmanca/asgi-lifespan](https://github.com/florimondmanca/asgi-lifespan#usage)의 `LifespanManager`를 사용하세요. /// @@ -94,6 +94,6 @@ response = client.get('/') /// tip | 팁 -테스트에 비동기 함수 호출을 통합할 때(예: MongoDB의 MotorClient를 사용할 때) `RuntimeError: Task attached to a different loop`를 마주친다면, 이벤트 루프가 필요한 객체는 async 함수 안에서만 인스턴스화해야 한다는 점을 기억하세요. 예를 들어 `@app.on_event("startup")` 콜백에서 인스턴스화할 수 있습니다. +테스트에 비동기 함수 호출을 통합할 때(예: [MongoDB의 MotorClient](https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop)를 사용할 때) `RuntimeError: Task attached to a different loop`를 마주친다면, 이벤트 루프가 필요한 객체는 async 함수 안에서만 인스턴스화해야 한다는 점을 기억하세요. 예를 들어 `@app.on_event("startup")` 콜백에서 인스턴스화할 수 있습니다. /// diff --git a/docs/ko/docs/advanced/behind-a-proxy.md b/docs/ko/docs/advanced/behind-a-proxy.md index 825592c060..d5f42dd374 100644 --- a/docs/ko/docs/advanced/behind-a-proxy.md +++ b/docs/ko/docs/advanced/behind-a-proxy.md @@ -16,9 +16,9 @@ 프록시 헤더는 다음과 같습니다: -* X-Forwarded-For -* X-Forwarded-Proto -* X-Forwarded-Host +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) /// @@ -60,7 +60,7 @@ https://mysuperapp.com/items/ /// tip | 팁 -HTTPS에 대해 더 알아보려면 가이드 [HTTPS에 대하여](../deployment/https.md){.internal-link target=_blank}를 확인하세요. +HTTPS에 대해 더 알아보려면 가이드 [HTTPS에 대하여](../deployment/https.md)를 확인하세요. /// @@ -149,14 +149,14 @@ IP `0.0.0.0`은 보통 해당 머신/서버에서 사용 가능한 모든 IP에 ```JSON hl_lines="4-8" { "openapi": "3.1.0", - // More stuff here + // 여기에 다른 내용이 더 있습니다 "servers": [ { "url": "/api/v1" } ], "paths": { - // More stuff here + // 여기에 다른 내용이 더 있습니다 } } ``` @@ -228,7 +228,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 서버(Uvicorn)는 그 `root_path`를 앱에 전달하는 것 외에는 다른 용도로 사용하지 않는다는 점을 기억하세요. -하지만 브라우저로 http://127.0.0.1:8000/app에 접속하면 정상 응답을 볼 수 있습니다: +하지만 브라우저로 [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app)에 접속하면 정상 응답을 볼 수 있습니다: ```JSON { @@ -251,9 +251,9 @@ Uvicorn은 프록시가 `http://127.0.0.1:8000/app`에서 Uvicorn에 접근할 ## Traefik으로 로컬 테스트하기 { #testing-locally-with-traefik } -Traefik을 사용하면, 경로 접두사가 제거되는 구성을 로컬에서 쉽게 실험할 수 있습니다. +[Traefik](https://docs.traefik.io/)을 사용하면, 경로 접두사가 제거되는 구성을 로컬에서 쉽게 실험할 수 있습니다. -Traefik 다운로드는 단일 바이너리이며, 압축 파일을 풀고 터미널에서 바로 실행할 수 있습니다. +[Traefik 다운로드](https://github.com/containous/traefik/releases)는 단일 바이너리이며, 압축 파일을 풀고 터미널에서 바로 실행할 수 있습니다. 그 다음 다음 내용을 가진 `traefik.toml` 파일을 생성하세요: @@ -330,7 +330,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 ### 응답 확인하기 { #check-the-responses } -이제 Uvicorn의 포트로 된 URL인 http://127.0.0.1:8000/app로 접속하면 정상 응답을 볼 수 있습니다: +이제 Uvicorn의 포트로 된 URL인 [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app)로 접속하면 정상 응답을 볼 수 있습니다: ```JSON { @@ -345,7 +345,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 /// -이제 Traefik의 포트가 포함되고 경로 접두사가 포함된 URL http://127.0.0.1:9999/api/v1/app을 여세요. +이제 Traefik의 포트가 포함되고 경로 접두사가 포함된 URL [http://127.0.0.1:9999/api/v1/app](http://127.0.0.1:9999/api/v1/app)을 여세요. 동일한 응답을 얻습니다: @@ -370,13 +370,13 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 앱에 접근하는 "공식" 방법은 우리가 정의한 경로 접두사를 가진 프록시를 통해서입니다. 따라서 기대하는 대로, URL에 경로 접두사가 없는 상태에서 Uvicorn이 직접 제공하는 docs UI를 시도하면, 프록시를 통해 접근된다고 가정하고 있기 때문에 동작하지 않습니다. -http://127.0.0.1:8000/docs에서 확인할 수 있습니다: +[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)에서 확인할 수 있습니다: 하지만 프록시(포트 `9999`)를 사용해 "공식" URL인 `/api/v1/docs`에서 docs UI에 접근하면, 올바르게 동작합니다! 🎉 -http://127.0.0.1:9999/api/v1/docs에서 확인할 수 있습니다: +[http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs)에서 확인할 수 있습니다: @@ -407,7 +407,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 ```JSON hl_lines="5-7" { "openapi": "3.1.0", - // More stuff here + // 여기에 다른 내용이 더 있습니다 "servers": [ { "url": "/api/v1" @@ -422,7 +422,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 } ], "paths": { - // More stuff here + // 여기에 다른 내용이 더 있습니다 } } ``` @@ -433,7 +433,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 /// -http://127.0.0.1:9999/api/v1/docs의 docs UI에서는 다음처럼 보입니다: +[http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs)의 docs UI에서는 다음처럼 보입니다: @@ -461,6 +461,6 @@ OpenAPI 사양에서 `servers` 속성은 선택 사항입니다. ## 서브 애플리케이션 마운트하기 { #mounting-a-sub-application } -프록시에서 `root_path`를 사용하면서도, [서브 애플리케이션 - 마운트](sub-applications.md){.internal-link target=_blank}에 설명된 것처럼 서브 애플리케이션을 마운트해야 한다면, 기대하는 대로 일반적으로 수행할 수 있습니다. +프록시에서 `root_path`를 사용하면서도, [서브 애플리케이션 - 마운트](sub-applications.md)에 설명된 것처럼 서브 애플리케이션을 마운트해야 한다면, 기대하는 대로 일반적으로 수행할 수 있습니다. FastAPI가 내부적으로 `root_path`를 똑똑하게 사용하므로, 그냥 동작합니다. ✨ diff --git a/docs/ko/docs/advanced/custom-response.md b/docs/ko/docs/advanced/custom-response.md index 6d54eaf2b1..e85ec3c743 100644 --- a/docs/ko/docs/advanced/custom-response.md +++ b/docs/ko/docs/advanced/custom-response.md @@ -1,16 +1,14 @@ # 사용자 정의 응답 - HTML, Stream, 파일, 기타 { #custom-response-html-stream-file-others } -기본적으로, **FastAPI** 응답을 `JSONResponse`를 사용하여 반환합니다. +기본적으로 **FastAPI**는 JSON 응답을 반환합니다. -이를 재정의 하려면 [응답을 직접 반환하기](response-directly.md){.internal-link target=_blank}에서 본 것처럼 `Response`를 직접 반환하면 됩니다. +[응답을 직접 반환하기](response-directly.md)에서 본 것처럼 `Response`를 직접 반환하여 이를 재정의할 수 있습니다. -그러나 `Response` (또는 `JSONResponse`와 같은 하위 클래스)를 직접 반환하면, 데이터가 자동으로 변환되지 않으며 (심지어 `response_model`을 선언했더라도), 문서화가 자동으로 생성되지 않습니다(예를 들어, 생성된 OpenAPI의 일부로 HTTP 헤더 `Content-Type`에 특정 "미디어 타입"을 포함하는 경우). +그러나 `Response`를 직접 반환하면(또는 `JSONResponse`와 같은 하위 클래스를 반환하면) 데이터가 자동으로 변환되지 않으며(비록 `response_model`을 선언했다 하더라도), 문서도 자동으로 생성되지 않습니다(예를 들어, 생성된 OpenAPI의 일부로 HTTP 헤더 `Content-Type`에 특정 "미디어 타입"을 포함하는 것 등). -하지만 *경로 처리 데코레이터*에서 `response_class` 매개변수를 사용하여 원하는 `Response`(예: 모든 `Response` 하위 클래스)를 선언할 수도 있습니다. +하지만 *경로 처리 데코레이터*에서 `response_class` 매개변수를 사용하여 사용할 `Response`(예: 어떤 `Response` 하위 클래스든)를 선언할 수도 있습니다. -*경로 처리 함수*에서 반환하는 내용은 해당 `Response`안에 포함됩니다. - -그리고 만약 그 `Response`가 `JSONResponse`와 `UJSONResponse`의 경우 처럼 JSON 미디어 타입(`application/json`)을 가지고 있다면, *경로 처리 데코레이터*에서 선언한 Pydantic의 `response_model`을 사용해 자동으로 변환(및 필터링) 됩니다. +*경로 처리 함수*에서 반환하는 내용은 해당 `Response` 안에 담깁니다. /// note | 참고 @@ -18,41 +16,27 @@ /// -## `ORJSONResponse` 사용하기 { #use-orjsonresponse } - -예를 들어, 성능을 극대화하려는 경우, `orjson`을 설치하여 사용하고 응답을 `ORJSONResponse`로 설정할 수 있습니다. - -사용하고자 하는 `Response` 클래스(하위 클래스)를 임포트한 후, *경로 처리 데코레이터*에서 선언하세요. - -대규모 응답의 경우, 딕셔너리를 반환하는 것보다 `Response`를 반환하는 것이 훨씬 빠릅니다. - -이유는 기본적으로, FastAPI가 내부의 모든 항목을 검사하고 JSON으로 직렬화할 수 있는지 확인하기 때문입니다. 이는 사용자 안내서에서 설명된 [JSON 호환 가능 인코더](../tutorial/encoder.md){.internal-link target=_blank}를 사용하는 방식과 동일합니다. 이를 통해 데이터베이스 모델과 같은 **임의의 객체**를 반환할 수 있습니다. - -하지만 반환하는 내용이 **JSON으로 직렬화 가능**하다고 확신하는 경우, 해당 내용을 응답 클래스에 직접 전달할 수 있으며, FastAPI가 반환 내용을 `jsonable_encoder`를 통해 처리한 뒤 응답 클래스에 전달하는 오버헤드를 피할 수 있습니다. +## JSON 응답 { #json-responses } -{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} +기본적으로 FastAPI는 JSON 응답을 반환합니다. -/// info | 정보 - -`response_class` 매개변수는 응답의 "미디어 타입"을 정의하는 데에도 사용됩니다. +[응답 모델](../tutorial/response-model.md)을 선언하면 FastAPI는 Pydantic을 사용해 데이터를 JSON으로 직렬화합니다. -이 경우, HTTP 헤더 `Content-Type`은 `application/json`으로 설정됩니다. +응답 모델을 선언하지 않으면 FastAPI는 [JSON 호환 가능 인코더](../tutorial/encoder.md)에서 설명한 `jsonable_encoder`를 사용해 데이터를 변환한 뒤 `JSONResponse`에 넣습니다. -그리고 이는 OpenAPI에 그대로 문서화됩니다. +`JSONResponse`처럼 JSON 미디어 타입(`application/json`)을 가진 `response_class`를 선언하면, 여러분이 *경로 처리 데코레이터*에서 선언한 Pydantic의 `response_model`로 데이터가 자동 변환(및 필터링)됩니다. 하지만 데이터의 JSON 바이트 직렬화 자체는 Pydantic이 수행하지 않고, `jsonable_encoder`로 변환한 후 `JSONResponse` 클래스에 전달하며, 그 클래스가 Python 표준 JSON 라이브러리를 사용해 바이트로 직렬화합니다. -/// +### JSON 성능 { #json-performance } -/// tip | 팁 +요약하면, 최대 성능이 필요하다면 [응답 모델](../tutorial/response-model.md)을 사용하고, *경로 처리 데코레이터*에 `response_class`를 선언하지 마세요. -`ORJSONResponse`는 FastAPI에서만 사용할 수 있고 Starlette에서는 사용할 수 없습니다. - -/// +{* ../../docs_src/response_model/tutorial001_01_py310.py ln[15:17] hl[16] *} ## HTML 응답 { #html-response } **FastAPI**에서 HTML 응답을 직접 반환하려면 `HTMLResponse`를 사용하세요. -* `HTMLResponse`를 임포트 합니다. +* `HTMLResponse`를 임포트합니다. * *경로 처리 데코레이터*의 `response_class` 매개변수로 `HTMLResponse`를 전달합니다. {* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} @@ -63,13 +47,13 @@ 이 경우, HTTP 헤더 `Content-Type`은 `text/html`로 설정됩니다. -그리고 이는 OpenAPI에 그대로 문서화 됩니다. +그리고 이는 OpenAPI에 그대로 문서화됩니다. /// ### `Response` 반환하기 { #return-a-response } -[응답을 직접 반환하기](response-directly.md){.internal-link target=_blank}에서 본 것 처럼, *경로 처리*에서 응답을 직접 반환하여 재정의할 수도 있습니다. +[응답을 직접 반환하기](response-directly.md)에서 본 것처럼, *경로 처리*에서 응답을 직접 반환하여 재정의할 수도 있습니다. 위의 예제와 동일하게 `HTMLResponse`를 반환하는 코드는 다음과 같을 수 있습니다: @@ -77,7 +61,7 @@ /// warning | 경고 -*경로 처리 함수*에서 직접 반환된 `Response`는 OpenAPI에 문서화되지 않습니다(예를들어, `Content-Type`이 문서화되지 않음) 자동 대화형 문서에서도 표시되지 않습니다. +*경로 처리 함수*에서 직접 반환된 `Response`는 OpenAPI에 문서화되지 않습니다(예를 들어, `Content-Type`이 문서화되지 않음) 그리고 자동 대화형 문서에도 표시되지 않습니다. /// @@ -87,54 +71,54 @@ /// -### OpenAPI에 문서화하고 `Response` 재정의 하기 { #document-in-openapi-and-override-response } +### OpenAPI에 문서화하고 `Response` 재정의하기 { #document-in-openapi-and-override-response } -함수 내부에서 응답을 재정의하면서 동시에 OpenAPI에서 "미디어 타입"을 문서화하고 싶다면, `response_class` 매게변수를 사용하면서 `Response` 객체를 반환할 수 있습니다. +함수 내부에서 응답을 재정의하면서 동시에 OpenAPI에서 "미디어 타입"을 문서화하고 싶다면, `response_class` 매개변수를 사용하면서 `Response` 객체를 반환할 수 있습니다. 이 경우 `response_class`는 OpenAPI *경로 처리*를 문서화하는 데만 사용되고, 실제로는 여러분이 반환한 `Response`가 그대로 사용됩니다. -#### `HTMLResponse`직접 반환하기 { #return-an-htmlresponse-directly } +#### `HTMLResponse` 직접 반환하기 { #return-an-htmlresponse-directly } 예를 들어, 다음과 같이 작성할 수 있습니다: {* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} -이 예제에서, `generate_html_response()` 함수는 HTML을 `str`로 반환하는 대신 이미 `Response`를 생성하고 반환합니다. +이 예제에서 `generate_html_response()` 함수는 HTML을 `str`로 반환하는 대신 이미 `Response`를 생성하고 반환합니다. -`generate_html_response()`를 호출한 결과를 반환함으로써, 기본적인 **FastAPI** 기본 동작을 재정의 하는 `Response`를 이미 반환하고 있습니다. +`generate_html_response()`를 호출한 결과를 반환함으로써, 기본적인 **FastAPI** 동작을 재정의하는 `Response`를 이미 반환하고 있습니다. -하지만 `response_class`에 `HTMLResponse`를 함께 전달했기 때문에, **FastAPI**는 이를 OpenAPI 및 대화형 문서에서 `text/html`로 HTML을 문서화 하는 방법을 알 수 있습니다. +하지만 `response_class`에 `HTMLResponse`를 함께 전달했기 때문에, **FastAPI**는 이를 OpenAPI 및 대화형 문서에서 `text/html`의 HTML로 문서화하는 방법을 알 수 있습니다: ## 사용 가능한 응답들 { #available-responses } -다음은 사용할 수 있는 몇가지 응답들 입니다. +다음은 사용할 수 있는 몇 가지 응답들입니다. -`Response`를 사용하여 다른 어떤 것도 반환 할수 있으며, 직접 하위 클래스를 만들 수도 있습니다. +`Response`를 사용하여 다른 어떤 것도 반환할 수 있으며, 직접 하위 클래스를 만들 수도 있습니다. /// note | 기술 세부사항 `from starlette.responses import HTMLResponse`를 사용할 수도 있습니다. -**FastAPI**는 개발자인 여러분의 편의를 위해 `starlette.responses`를 `fastapi.responses`로 제공 하지만, 대부분의 사용 가능한 응답은 Starlette에서 직접 가져옵니다. +**FastAPI**는 개발자인 여러분의 편의를 위해 `starlette.responses`를 `fastapi.responses`로 동일하게 제공하지만, 대부분의 사용 가능한 응답은 Starlette에서 직접 가져옵니다. /// ### `Response` { #response } -기본 `Response` 클래스는 다른 모든 응답 클래스의 부모 클래스 입니다. +기본 `Response` 클래스이며, 다른 모든 응답 클래스가 이를 상속합니다. 이 클래스를 직접 반환할 수 있습니다. 다음 매개변수를 받을 수 있습니다: * `content` - `str` 또는 `bytes`. -* `status_code` - HTTP 상태코드를 나타내는 `int`. +* `status_code` - HTTP 상태 코드를 나타내는 `int`. * `headers` - 문자열로 이루어진 `dict`. * `media_type` - 미디어 타입을 나타내는 `str` 예: `"text/html"`. -FastAPI (실제로는 Starlette)가 자동으로 Content-Length 헤더를 포함시킵니다. 또한 `media_type`에 기반하여 Content-Type 헤더를 포함하며, 텍스트 타입의 경우 문자 집합을 추가 합니다. +FastAPI(정확히는 Starlette)가 자동으로 Content-Length 헤더를 포함시킵니다. 또한 `media_type`에 기반하여 Content-Type 헤더를 포함하며, 텍스트 타입의 경우 문자 집합을 추가합니다. {* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} @@ -154,37 +138,11 @@ FastAPI (실제로는 Starlette)가 자동으로 Content-Length 헤더를 포함 이는 위에서 설명했듯이 **FastAPI**에서 기본적으로 사용되는 응답 형식입니다. -### `ORJSONResponse` { #orjsonresponse } - - `orjson`을 사용하여 빠른 JSON 응답을 제공하는 대안입니다. 위에서 설명한 내용과 같습니다. - -/// info | 정보 - -이를 사용하려면 `orjson`을 설치해야합니다. 예: `pip install orjson`. - -/// - -### `UJSONResponse` { #ujsonresponse } - -`ujson`을 사용한 또 다른 JSON 응답 형식입니다. - -/// info | 정보 - -이 응답을 사용하려면 `ujson`을 설치해야합니다. 예: `pip install ujson`. - -/// +/// note | 기술 세부사항 -/// warning | 경고 +하지만 응답 모델 또는 반환 타입을 선언한 경우, 해당 모델이 데이터를 JSON으로 직렬화하는 데 직접 사용되며, 올바른 JSON 미디어 타입의 응답이 `JSONResponse` 클래스를 사용하지 않고 바로 반환됩니다. -`ujson` 은 일부 예외 경우를 처리하는 데 있어 Python 내장 구현보다 덜 엄격합니다. - -/// - -{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} - -/// tip | 팁 - -`ORJSONResponse`가 더 빠른 대안일 가능성이 있습니다. +이 방식이 최상의 성능을 얻는 이상적인 방법입니다. /// @@ -192,7 +150,7 @@ FastAPI (실제로는 Starlette)가 자동으로 Content-Length 헤더를 포함 HTTP 리디렉션 응답을 반환합니다. 기본적으로 상태 코드는 307(임시 리디렉션)으로 설정됩니다. -`RedirectResponse`를 직접 반환할 수 있습니다. +`RedirectResponse`를 직접 반환할 수 있습니다: {* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} @@ -205,7 +163,7 @@ HTTP 리디렉션 응답을 반환합니다. 기본적으로 상태 코드는 30 이 경우, *경로 처리* 함수에서 URL을 직접 반환할 수 있습니다. -이 경우, 사용되는 `status_code`는 `RedirectResponse`의 기본값인 `307` 입니다. +이 경우, 사용되는 `status_code`는 `RedirectResponse`의 기본값인 `307`입니다. --- @@ -215,31 +173,25 @@ HTTP 리디렉션 응답을 반환합니다. 기본적으로 상태 코드는 30 ### `StreamingResponse` { #streamingresponse } -비동기 제너레이터 또는 일반 제너레이터/이터레이터를 받아 응답 본문을 스트리밍 합니다. - -{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} - -#### 파일과 같은 객체를 사용한 `StreamingResponse` { #using-streamingresponse-with-file-like-objects } +비동기 제너레이터 또는 일반 제너레이터/이터레이터(`yield`가 있는 함수)를 받아 응답 본문을 스트리밍합니다. -file-like 객체(예: `open()`으로 반환된 객체)가 있는 경우, 해당 file-like 객체를 반복(iterate)하는 제너레이터 함수를 만들 수 있습니다. +{* ../../docs_src/custom_response/tutorial007_py310.py hl[3,16] *} -이 방식으로, 파일 전체를 메모리에 먼저 읽어들일 필요 없이, 제너레이터 함수를 `StreamingResponse`에 전달하여 반환할 수 있습니다. - -이 방식은 클라우드 스토리지, 비디오 처리 등의 다양한 라이브러리와 함께 사용할 수 있습니다. +/// note | 기술 세부사항 -{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} +`async` 작업은 `await`에 도달했을 때만 취소될 수 있습니다. `await`가 없으면 제너레이터(`yield`가 있는 함수)는 제대로 취소될 수 없고, 취소가 요청된 후에도 계속 실행될 수 있습니다. -1. 이것이 제너레이터 함수입니다. `yield` 문을 포함하고 있으므로 "제너레이터 함수"입니다. -2. `with` 블록을 사용함으로써, 제너레이터 함수가 완료된 후 파일과 같은 객체가 닫히도록 합니다. 즉, 응답 전송이 끝난 후 닫힙니다. -3. 이 `yield from`은 함수가 `file_like`라는 객체를 반복(iterate)하도록 합니다. 반복된 각 부분은 이 제너레이터 함수(`iterfile`)에서 생성된 것처럼 `yield` 됩니다. +이 작은 예제는 어떤 `await`도 필요하지 않으므로, 이벤트 루프가 취소를 처리할 기회를 주기 위해 `await anyio.sleep(0)`를 추가합니다. - 이렇게 하면 "생성(generating)" 작업을 내부적으로 다른 무언가에 위임하는 제너레이터 함수가 됩니다. +대규모 또는 무한 스트림에서는 더욱 중요합니다. - 이 방식을 사용하면 `with` 블록 안에서 파일을 열 수 있어, 작업이 완료된 후 파일과 같은 객체가 닫히는 것을 보장할 수 있습니다. +/// /// tip | 팁 -여기서 표준 `open()`을 사용하고 있기 때문에 `async`와 `await`를 지원하지 않습니다. 따라서 경로 처리는 일반 `def`로 선언합니다. +`StreamingResponse`를 직접 반환하는 대신, [데이터 스트리밍](./stream-data.md)에서의 스타일을 따르는 것이 더 편리하며 백그라운드에서 취소 처리를 해줍니다. + +JSON Lines를 스트리밍한다면, [JSON Lines 스트리밍](../tutorial/stream-json-lines.md) 튜토리얼을 확인하세요. /// @@ -268,9 +220,9 @@ HTTP 리디렉션 응답을 반환합니다. 기본적으로 상태 코드는 30 `Response`를 상속받아 사용자 정의 응답 클래스를 생성하고 사용할 수 있습니다. -예를 들어, 포함된 `ORJSONResponse` 클래스에서 사용되지 않는 설정으로 `orjson`을 사용하고 싶다고 가정해봅시다. +예를 들어, [`orjson`](https://github.com/ijl/orjson)을 일부 설정과 함께 사용하고 싶다고 가정해봅시다. -만약 들여쓰기 및 포맷된 JSON을 반환하고 싶다면, `orjson.OPT_INDENT_2` 옵션을 사용할 수 있습니다. +들여쓰기 및 포맷된 JSON을 반환하고 싶다면, orjson 옵션 `orjson.OPT_INDENT_2`를 사용할 수 있습니다. `CustomORJSONResponse`를 생성할 수 있습니다. 여기서 핵심은 `Response.render(content)` 메서드를 생성하여 내용을 `bytes`로 반환하는 것입니다: @@ -292,13 +244,21 @@ HTTP 리디렉션 응답을 반환합니다. 기본적으로 상태 코드는 30 물론 JSON 포맷팅보다 더 유용하게 활용할 방법을 찾을 수 있을 것입니다. 😉 +### `orjson` 또는 응답 모델 { #orjson-or-response-model } + +성능이 목적이라면, `orjson` 응답을 사용하는 것보다 [응답 모델](../tutorial/response-model.md)을 사용하는 편이 더 나을 가능성이 큽니다. + +응답 모델을 사용하면 FastAPI는 중간 단계(예: `jsonable_encoder`로의 변환) 없이 Pydantic을 사용해 데이터를 JSON으로 직렬화합니다. 이런 중간 단계는 다른 경우에 발생합니다. + +그리고 내부적으로 Pydantic은 JSON 직렬화를 위해 `orjson`과 동일한 Rust 기반 메커니즘을 사용하므로, 응답 모델만으로도 이미 최상의 성능을 얻게 됩니다. + ## 기본 응답 클래스 { #default-response-class } -**FastAPI** 클래스 객체 또는 `APIRouter`를 생성할 때 기본적으로 사용할 응답 클래스를 지정할 수 있습니다. +**FastAPI** 클래스 인스턴스 또는 `APIRouter`를 생성할 때 기본으로 사용할 응답 클래스를 지정할 수 있습니다. 이를 정의하는 매개변수는 `default_response_class`입니다. -아래 예제에서 **FastAPI**는 모든 *경로 처리*에서 기본적으로 `JSONResponse` 대신 `ORJSONResponse`를 사용합니다. +아래 예제에서 **FastAPI**는 모든 *경로 처리*에서 JSON 대신 기본적으로 `HTMLResponse`를 사용합니다. {* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} @@ -310,4 +270,4 @@ HTTP 리디렉션 응답을 반환합니다. 기본적으로 상태 코드는 30 ## 추가 문서화 { #additional-documentation } -OpenAPI에서 `responses`를 사용하여 미디어 타입 및 기타 세부 정보를 선언할 수도 있습니다: [OpenAPI에서 추가 응답](additional-responses.md){.internal-link target=_blank}. +OpenAPI에서 `responses`를 사용하여 미디어 타입 및 기타 세부 정보를 선언할 수도 있습니다: [OpenAPI에서 추가 응답](additional-responses.md). diff --git a/docs/ko/docs/advanced/dataclasses.md b/docs/ko/docs/advanced/dataclasses.md index 0210812b6e..77e8d0464c 100644 --- a/docs/ko/docs/advanced/dataclasses.md +++ b/docs/ko/docs/advanced/dataclasses.md @@ -2,11 +2,11 @@ FastAPI는 **Pydantic** 위에 구축되어 있으며, 지금까지는 Pydantic 모델을 사용해 요청과 응답을 선언하는 방법을 보여드렸습니다. -하지만 FastAPI는 `dataclasses`도 같은 방식으로 사용하는 것을 지원합니다: +하지만 FastAPI는 [`dataclasses`](https://docs.python.org/3/library/dataclasses.html)도 같은 방식으로 사용하는 것을 지원합니다: {* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} -이는 **Pydantic** 덕분에 여전히 지원되는데, Pydantic이 `dataclasses`에 대한 내부 지원을 제공하기 때문입니다. +이는 **Pydantic** 덕분에 여전히 지원되는데, Pydantic이 [`dataclasses`에 대한 내부 지원](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel)을 제공하기 때문입니다. 따라서 위 코드처럼 Pydantic을 명시적으로 사용하지 않더라도, FastAPI는 Pydantic을 사용해 표준 dataclasses를 Pydantic의 dataclasses 변형으로 변환합니다. @@ -18,7 +18,7 @@ FastAPI는 **Pydantic** 위에 구축되어 있으며, 지금까지는 Pydantic 이는 Pydantic 모델을 사용할 때와 같은 방식으로 동작합니다. 그리고 실제로도 내부적으로는 Pydantic을 사용해 같은 방식으로 구현됩니다. -/// info | 정보 +/// info dataclasses는 Pydantic 모델이 할 수 있는 모든 것을 할 수는 없다는 점을 기억하세요. @@ -74,7 +74,7 @@ dataclass는 자동으로 Pydantic dataclass로 변환됩니다. 언제나처럼 FastAPI에서는 필요에 따라 `def`와 `async def`를 조합해 사용할 수 있습니다. - 어떤 것을 언제 사용해야 하는지 다시 확인하고 싶다면, [`async`와 `await`](../async.md#in-a-hurry){.internal-link target=_blank} 문서의 _"급하신가요?"_ 섹션을 확인하세요. + 어떤 것을 언제 사용해야 하는지 다시 확인하고 싶다면, [`async`와 `await`](../async.md#in-a-hurry) 문서의 _"급하신가요?"_ 섹션을 확인하세요. 9. 이 *경로 처리 함수*는 dataclasses를(물론 반환할 수도 있지만) 반환하지 않고, 내부 데이터를 담은 딕셔너리들의 리스트를 반환합니다. @@ -88,7 +88,7 @@ dataclass는 자동으로 Pydantic dataclass로 변환됩니다. `dataclasses`를 다른 Pydantic 모델과 조합하거나, 이를 상속하거나, 여러분의 모델에 포함하는 등의 작업도 할 수 있습니다. -자세한 내용은 dataclasses에 관한 Pydantic 문서를 참고하세요. +자세한 내용은 [dataclasses에 관한 Pydantic 문서](https://docs.pydantic.dev/latest/concepts/dataclasses/)를 참고하세요. ## 버전 { #version } diff --git a/docs/ko/docs/advanced/events.md b/docs/ko/docs/advanced/events.md index f1dd8397a0..708ad443ff 100644 --- a/docs/ko/docs/advanced/events.md +++ b/docs/ko/docs/advanced/events.md @@ -150,11 +150,11 @@ async with lifespan(app): 호기심 많은 분들을 위한 기술적인 세부사항입니다. 🤓 -내부적으로 ASGI 기술 사양에서는 이것이 Lifespan Protocol의 일부이며, `startup`과 `shutdown`이라는 이벤트를 정의합니다. +내부적으로 ASGI 기술 사양에서는 이것이 [Lifespan Protocol](https://asgi.readthedocs.io/en/latest/specs/lifespan.html)의 일부이며, `startup`과 `shutdown`이라는 이벤트를 정의합니다. /// info | 정보 -Starlette `lifespan` 핸들러에 대해서는 Starlette의 Lifespan 문서에서 더 읽어볼 수 있습니다. +Starlette `lifespan` 핸들러에 대해서는 [Starlette의 Lifespan 문서](https://www.starlette.dev/lifespan/)에서 더 읽어볼 수 있습니다. 또한 코드의 다른 영역에서 사용할 수 있는 lifespan 상태를 처리하는 방법도 포함되어 있습니다. @@ -162,4 +162,4 @@ Starlette `lifespan` 핸들러에 대해서는 OpenAPI Generator가 있으며, **다양한 프로그래밍 언어**를 지원하고 OpenAPI 사양으로부터 SDK를 생성할 수 있습니다. +다양하게 활용할 수 있는 옵션으로 [OpenAPI Generator](https://openapi-generator.tech/)가 있으며, **다양한 프로그래밍 언어**를 지원하고 OpenAPI 사양으로부터 SDK를 생성할 수 있습니다. -**TypeScript 클라이언트**의 경우 Hey API는 TypeScript 생태계에 최적화된 경험을 제공하는 목적에 맞게 설계된 솔루션입니다. +**TypeScript 클라이언트**의 경우 [Hey API](https://heyapi.dev/)는 TypeScript 생태계에 최적화된 경험을 제공하는 목적에 맞게 설계된 솔루션입니다. -더 많은 SDK 생성기는 OpenAPI.Tools에서 확인할 수 있습니다. +더 많은 SDK 생성기는 [OpenAPI.Tools](https://openapi.tools/#sdk)에서 확인할 수 있습니다. /// tip | 팁 @@ -24,15 +24,15 @@ FastAPI는 **OpenAPI 3.1** 사양을 자동으로 생성하므로, 사용하는 이 섹션에서는 FastAPI를 후원하는 회사들이 제공하는 **벤처 투자 기반** 및 **기업 지원** 솔루션을 소개합니다. 이 제품들은 고품질로 생성된 SDK에 더해 **추가 기능**과 **통합**을 제공합니다. -✨ [**FastAPI 후원하기**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨를 통해, 이 회사들은 프레임워크와 그 **생태계**가 건강하고 **지속 가능**하게 유지되도록 돕습니다. +✨ [**FastAPI 후원하기**](../help-fastapi.md#sponsor-the-author) ✨를 통해, 이 회사들은 프레임워크와 그 **생태계**가 건강하고 **지속 가능**하게 유지되도록 돕습니다. 또한 이들의 후원은 FastAPI **커뮤니티**(여러분)에 대한 강한 헌신을 보여주며, **좋은 서비스**를 제공하는 것뿐 아니라, 견고하고 활발한 프레임워크인 FastAPI를 지원하는 데에도 관심이 있음을 나타냅니다. 🙇 예를 들어 다음을 사용해 볼 수 있습니다: -* Speakeasy -* Stainless -* liblab +* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) +* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) +* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) 이 중 일부는 오픈 소스이거나 무료 티어를 제공하므로, 비용 부담 없이 사용해 볼 수 있습니다. 다른 상용 SDK 생성기도 있으며 온라인에서 찾을 수 있습니다. 🤓 @@ -42,7 +42,7 @@ FastAPI는 **OpenAPI 3.1** 사양을 자동으로 생성하므로, 사용하는 {* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} -*path operation*에서 요청 페이로드와 응답 페이로드에 사용하는 모델을 `Item`, `ResponseMessage` 모델로 정의하고 있다는 점에 주목하세요. +*경로 처리*에서 요청 페이로드와 응답 페이로드에 사용하는 모델을 `Item`, `ResponseMessage` 모델로 정의하고 있다는 점에 주목하세요. ### API 문서 { #api-docs } @@ -66,7 +66,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client 이 명령은 `./src/client`에 TypeScript SDK를 생성합니다. -`@hey-api/openapi-ts` 설치 방법생성된 결과물은 해당 웹사이트에서 확인할 수 있습니다. +[`@hey-api/openapi-ts` 설치 방법](https://heyapi.dev/openapi-ts/get-started)과 [생성된 결과물](https://heyapi.dev/openapi-ts/output)은 해당 웹사이트에서 확인할 수 있습니다. ### SDK 사용하기 { #using-the-sdk } @@ -94,7 +94,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client ## 태그가 있는 FastAPI 앱 { #fastapi-app-with-tags } -대부분의 경우 FastAPI 앱은 더 커지고, 서로 다른 *path operations* 그룹을 분리하기 위해 태그를 사용하게 될 가능성이 큽니다. +대부분의 경우 FastAPI 앱은 더 커지고, 서로 다른 *경로 처리* 그룹을 분리하기 위해 태그를 사용하게 될 가능성이 큽니다. 예를 들어 **items** 섹션과 **users** 섹션이 있고, 이를 태그로 분리할 수 있습니다: @@ -121,9 +121,9 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) ``` -...이는 클라이언트 생성기가 각 *path operation*에 대해 OpenAPI 내부의 **operation ID**를 사용하기 때문입니다. +...이는 클라이언트 생성기가 각 *경로 처리*에 대해 OpenAPI 내부의 **operation ID**를 사용하기 때문입니다. -OpenAPI는 모든 *path operations* 전체에서 operation ID가 각각 유일해야 한다고 요구합니다. 그래서 FastAPI는 operation ID가 유일하도록 **함수 이름**, **경로**, **HTTP method/operation**을 조합해 operation ID를 생성합니다. +OpenAPI는 모든 *경로 처리* 전체에서 operation ID가 각각 유일해야 한다고 요구합니다. 그래서 FastAPI는 operation ID가 유일하도록 **함수 이름**, **경로**, **HTTP method/operation**을 조합해 operation ID를 생성합니다. 하지만 다음에서 이를 개선하는 방법을 보여드리겠습니다. 🤓 @@ -133,15 +133,15 @@ OpenAPI는 모든 *path operations* 전체에서 operation ID가 각각 유일 이 경우 operation ID가 다른 방식으로도 **유일**하도록 보장해야 합니다. -예를 들어 각 *path operation*이 태그를 갖도록 한 다음, **태그**와 *path operation* **이름**(함수 이름)을 기반으로 operation ID를 생성할 수 있습니다. +예를 들어 각 *경로 처리*이 태그를 갖도록 한 다음, **태그**와 *경로 처리* **이름**(함수 이름)을 기반으로 operation ID를 생성할 수 있습니다. ### 유일 ID 생성 함수 커스터마이징 { #custom-generate-unique-id-function } -FastAPI는 각 *path operation*에 대해 **유일 ID**를 사용하며, 이는 **operation ID** 및 요청/응답에 필요한 커스텀 모델 이름에도 사용됩니다. +FastAPI는 각 *경로 처리*에 대해 **유일 ID**를 사용하며, 이는 **operation ID** 및 요청/응답에 필요한 커스텀 모델 이름에도 사용됩니다. 이 함수를 커스터마이징할 수 있습니다. 이 함수는 `APIRoute`를 받아 문자열을 반환합니다. -예를 들어 아래에서는 첫 번째 태그(대부분 태그는 하나만 있을 것입니다)와 *path operation* 이름(함수 이름)을 사용합니다. +예를 들어 아래에서는 첫 번째 태그(대부분 태그는 하나만 있을 것입니다)와 *경로 처리* 이름(함수 이름)을 사용합니다. 그 다음 이 커스텀 함수를 `generate_unique_id_function` 매개변수로 **FastAPI**에 전달할 수 있습니다: @@ -201,7 +201,7 @@ npx @hey-api/openapi-ts -i ./openapi.json -o src/client 또한 모든 것에 대해 **인라인 오류**도 확인할 수 있습니다. -그리고 백엔드 코드를 업데이트한 뒤 프론트엔드를 **재생성(regenerate)**하면, 새 *path operations*가 메서드로 추가되고 기존 것은 제거되며, 그 밖의 변경 사항도 생성된 코드에 반영됩니다. 🤓 +그리고 백엔드 코드를 업데이트한 뒤 프론트엔드를 **재생성(regenerate)**하면, 새 *경로 처리*가 메서드로 추가되고 기존 것은 제거되며, 그 밖의 변경 사항도 생성된 코드에 반영됩니다. 🤓 이는 무언가 변경되면 그 변경이 클라이언트 코드에도 자동으로 **반영**된다는 뜻입니다. 또한 클라이언트를 **빌드(build)**하면 사용된 데이터가 **불일치(mismatch)**할 경우 오류가 발생합니다. diff --git a/docs/ko/docs/advanced/index.md b/docs/ko/docs/advanced/index.md index 6212a7279c..feb91d5a6b 100644 --- a/docs/ko/docs/advanced/index.md +++ b/docs/ko/docs/advanced/index.md @@ -2,7 +2,7 @@ ## 추가 기능 { #additional-features } -메인 [자습서 - 사용자 안내서](../tutorial/index.md){.internal-link target=_blank}는 여러분이 **FastAPI**의 모든 주요 기능을 둘러보시기에 충분할 것입니다. +메인 [자습서 - 사용자 안내서](../tutorial/index.md)는 여러분이 **FastAPI**의 모든 주요 기능을 둘러보시기에 충분할 것입니다. 이어지는 장에서는 여러분이 다른 옵션, 구성 및 추가 기능을 보실 수 있습니다. @@ -16,6 +16,6 @@ ## 자습서를 먼저 읽으십시오 { #read-the-tutorial-first } -여러분은 메인 [자습서 - 사용자 안내서](../tutorial/index.md){.internal-link target=_blank}의 지식으로 **FastAPI**의 대부분의 기능을 사용하실 수 있습니다. +여러분은 메인 [자습서 - 사용자 안내서](../tutorial/index.md)의 지식으로 **FastAPI**의 대부분의 기능을 사용하실 수 있습니다. 이어지는 장들은 여러분이 메인 자습서 - 사용자 안내서를 이미 읽으셨으며 주요 아이디어를 알고 계신다고 가정합니다. diff --git a/docs/ko/docs/advanced/middleware.md b/docs/ko/docs/advanced/middleware.md index f6f7bbc966..7443cf4241 100644 --- a/docs/ko/docs/advanced/middleware.md +++ b/docs/ko/docs/advanced/middleware.md @@ -1,8 +1,8 @@ # 고급 Middleware { #advanced-middleware } -메인 튜토리얼에서 애플리케이션에 [커스텀 Middleware](../tutorial/middleware.md){.internal-link target=_blank}를 추가하는 방법을 읽었습니다. +메인 튜토리얼에서 애플리케이션에 [커스텀 Middleware](../tutorial/middleware.md)를 추가하는 방법을 읽었습니다. -그리고 [`CORSMiddleware`로 CORS 처리하기](../tutorial/cors.md){.internal-link target=_blank}도 읽었습니다. +그리고 [`CORSMiddleware`로 CORS 처리하기](../tutorial/cors.md)도 읽었습니다. 이 섹션에서는 다른 middleware들을 사용하는 방법을 살펴보겠습니다. @@ -91,7 +91,7 @@ HTTP Host Header 공격을 방어하기 위해, 들어오는 모든 요청에 예를 들어: -* Uvicorn의 `ProxyHeadersMiddleware` -* MessagePack +* [Uvicorn의 `ProxyHeadersMiddleware`](https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py) +* [MessagePack](https://github.com/florimondmanca/msgpack-asgi) -사용 가능한 다른 middleware를 보려면 Starlette의 Middleware 문서ASGI Awesome List를 확인하세요. +사용 가능한 다른 middleware를 보려면 [Starlette의 Middleware 문서](https://www.starlette.dev/middleware/)와 [ASGI Awesome List](https://github.com/florimondmanca/awesome-asgi)를 확인하세요. diff --git a/docs/ko/docs/advanced/openapi-callbacks.md b/docs/ko/docs/advanced/openapi-callbacks.md index 95f90d73cc..fa71acdcf8 100644 --- a/docs/ko/docs/advanced/openapi-callbacks.md +++ b/docs/ko/docs/advanced/openapi-callbacks.md @@ -35,7 +35,7 @@ /// tip | 팁 -`callback_url` 쿼리 파라미터는 Pydantic의 Url 타입을 사용합니다. +`callback_url` 쿼리 파라미터는 Pydantic의 [Url](https://docs.pydantic.dev/latest/api/networks/) 타입을 사용합니다. /// @@ -66,7 +66,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) 실제 콜백은 단지 HTTP 요청입니다. -콜백을 직접 구현할 때는 HTTPXRequests 같은 것을 사용할 수 있습니다. +콜백을 직접 구현할 때는 [HTTPX](https://www.python-httpx.org)나 [Requests](https://requests.readthedocs.io/) 같은 것을 사용할 수 있습니다. /// @@ -106,11 +106,11 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) 일반적인 *경로 처리*와의 주요 차이점은 2가지입니다: * 실제 코드를 가질 필요가 없습니다. 여러분의 앱은 이 코드를 절대 호출하지 않기 때문입니다. 이는 *external API*를 문서화하는 데만 사용됩니다. 따라서 함수는 그냥 `pass`만 있어도 됩니다. -* *path*에는 OpenAPI 3 expression(자세한 내용은 아래 참고)이 포함될 수 있으며, 이를 통해 *여러분의 API*로 보내진 원래 요청의 파라미터와 일부 값을 변수로 사용할 수 있습니다. +* *path*에는 [OpenAPI 3 표현식](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)(자세한 내용은 아래 참고)이 포함될 수 있으며, 이를 통해 *여러분의 API*로 보내진 원래 요청의 파라미터와 일부 값을 변수로 사용할 수 있습니다. ### 콜백 경로 표현식 { #the-callback-path-expression } -콜백 *path*는 *여러분의 API*로 보내진 원래 요청의 일부를 포함할 수 있는 OpenAPI 3 expression을 가질 수 있습니다. +콜백 *path*는 *여러분의 API*로 보내진 원래 요청의 일부를 포함할 수 있는 [OpenAPI 3 표현식](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)을 가질 수 있습니다. 이 경우, 다음 `str`입니다: @@ -179,7 +179,7 @@ https://www.external.org/events/invoices/2expen51ve ### 문서 확인하기 { #check-the-docs } -이제 앱을 실행하고 http://127.0.0.1:8000/docs로 이동하세요. +이제 앱을 실행하고 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)로 이동하세요. *경로 처리*에 대해 "Callbacks" 섹션을 포함한 문서가 표시되며, *external API*가 어떤 형태여야 하는지 확인할 수 있습니다: diff --git a/docs/ko/docs/advanced/openapi-webhooks.md b/docs/ko/docs/advanced/openapi-webhooks.md index 8651c4176c..e40a7bb186 100644 --- a/docs/ko/docs/advanced/openapi-webhooks.md +++ b/docs/ko/docs/advanced/openapi-webhooks.md @@ -48,7 +48,7 @@ webhook에서는 실제로(`/items/` 같은) *경로(path)*를 선언하지 않 ### 문서 확인하기 { #check-the-docs } -이제 앱을 실행하고 http://127.0.0.1:8000/docs로 이동하세요. +이제 앱을 실행하고 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)로 이동하세요. 문서에 일반적인 *경로 처리*가 보이고, 이제는 일부 **webhooks**도 함께 보일 것입니다: diff --git a/docs/ko/docs/advanced/path-operation-advanced-configuration.md b/docs/ko/docs/advanced/path-operation-advanced-configuration.md index da8e43bd3e..253a6f3021 100644 --- a/docs/ko/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/ko/docs/advanced/path-operation-advanced-configuration.md @@ -60,7 +60,7 @@ OpenAPI에 사용할 *경로 처리 함수*의 docstring 줄 수를 제한할 모델, 상태 코드 등과 함께 추가 응답도 선언할 수 있습니다. -이에 대한 문서의 전체 장이 있으니, [OpenAPI의 추가 응답](additional-responses.md){.internal-link target=_blank}에서 읽어보세요. +이에 대한 문서의 전체 장이 있으니, [OpenAPI의 추가 응답](additional-responses.md)에서 읽어보세요. ## OpenAPI Extra { #openapi-extra } @@ -68,7 +68,7 @@ OpenAPI에 사용할 *경로 처리 함수*의 docstring 줄 수를 제한할 /// note | 기술 세부사항 -OpenAPI 명세에서는 이를 Operation Object라고 부릅니다. +OpenAPI 명세에서는 이를 [Operation Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object)라고 부릅니다. /// @@ -82,7 +82,7 @@ OpenAPI 명세에서는 이를 Starlette의 문서에서 확인할 수 있습니다. +사용 가능한 모든 매개변수와 옵션은 [Starlette의 문서](https://www.starlette.dev/responses/#set-cookie)에서 확인할 수 있습니다. diff --git a/docs/ko/docs/advanced/response-directly.md b/docs/ko/docs/advanced/response-directly.md index c43b11a4d5..301a259b2f 100644 --- a/docs/ko/docs/advanced/response-directly.md +++ b/docs/ko/docs/advanced/response-directly.md @@ -2,19 +2,23 @@ **FastAPI**에서 *경로 처리(path operation)*를 생성할 때, 일반적으로 `dict`, `list`, Pydantic 모델, 데이터베이스 모델 등의 데이터를 반환할 수 있습니다. -기본적으로 **FastAPI**는 [JSON 호환 가능 인코더](../tutorial/encoder.md){.internal-link target=_blank}에 설명된 `jsonable_encoder`를 사용해 해당 반환 값을 자동으로 JSON으로 변환합니다. +[응답 모델](../tutorial/response-model.md)을 선언하면 FastAPI는 Pydantic을 사용해 데이터를 JSON으로 직렬화합니다. -그런 다음, 내부적으로는 JSON 호환 데이터(예: `dict`)를 `JSONResponse`에 넣어 클라이언트로 응답을 전송하는 데 사용합니다. +응답 모델을 선언하지 않으면, FastAPI는 [JSON 호환 가능 인코더](../tutorial/encoder.md)에 설명된 `jsonable_encoder`를 사용해 데이터를 변환하고 이를 `JSONResponse`에 넣습니다. -하지만 *경로 처리*에서 `JSONResponse`를 직접 반환할 수도 있습니다. +또한 `JSONResponse`를 직접 생성해 반환할 수도 있습니다. -예를 들어, 사용자 정의 헤더나 쿠키를 반환해야 하는 경우에 유용할 수 있습니다. +/// tip | 팁 + +일반적으로 `JSONResponse`를 직접 반환하는 것보다 [응답 모델](../tutorial/response-model.md)을 사용하는 편이 성능이 훨씬 좋습니다. 이렇게 하면 Pydantic이 Rust에서 데이터를 직렬화합니다. + +/// ## `Response` 반환하기 { #return-a-response } -사실, `Response` 또는 그 하위 클래스를 반환할 수 있습니다. +`Response` 또는 그 하위 클래스를 반환할 수 있습니다. -/// tip | 팁 +/// info | 정보 `JSONResponse` 자체도 `Response`의 하위 클래스입니다. @@ -26,6 +30,8 @@ Pydantic 모델로 데이터 변환을 수행하지 않으며, 내용을 다른 이로 인해 많은 유연성을 얻을 수 있습니다. 어떤 데이터 유형이든 반환할 수 있고, 데이터 선언이나 유효성 검사를 재정의할 수 있습니다. +또한 많은 책임도 따릅니다. 반환하는 데이터가 올바르고, 올바른 형식이며, 직렬화가 가능하도록 여러분이 직접 보장해야 합니다. + ## `Response`에서 `jsonable_encoder` 사용하기 { #using-the-jsonable-encoder-in-a-response } **FastAPI**는 반환하는 `Response`에 아무런 변경도 하지 않으므로, 그 내용이 준비되어 있는지 확인해야 합니다. @@ -50,16 +56,28 @@ Pydantic 모델로 데이터 변환을 수행하지 않으며, 내용을 다른 이제, 이를 사용해 사용자 정의 응답을 반환하는 방법을 알아보겠습니다. -예를 들어 XML 응답을 반환하고 싶다고 가정해 보겠습니다. +예를 들어 [XML](https://en.wikipedia.org/wiki/XML) 응답을 반환하고 싶다고 가정해 보겠습니다. XML 내용을 문자열에 넣고, 이를 `Response`에 넣어 반환할 수 있습니다: {* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} +## 응답 모델 동작 방식 { #how-a-response-model-works } + +경로 처리에서 [응답 모델 - 반환 타입](../tutorial/response-model.md)을 선언하면 **FastAPI**는 Pydantic을 사용해 데이터를 JSON으로 직렬화합니다. + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +이는 Rust 측에서 처리되므로, 일반적인 Python과 `JSONResponse` 클래스로 수행하는 것보다 성능이 훨씬 좋습니다. + +`response_model` 또는 반환 타입을 사용할 때 FastAPI는 `jsonable_encoder`로 데이터를 변환(이는 더 느립니다)하지도 않고, `JSONResponse` 클래스를 사용하지도 않습니다. + +대신 응답 모델(또는 반환 타입)을 사용해 Pydantic이 생성한 JSON 바이트를 가져와, JSON에 맞는 미디어 타입(`application/json`)을 가진 `Response`를 직접 반환합니다. + ## 참고 사항 { #notes } `Response`를 직접 반환할 때, 그 데이터는 자동으로 유효성 검사되거나, 변환(직렬화)되거나, 문서화되지 않습니다. -그러나 [OpenAPI에서 추가 응답](additional-responses.md){.internal-link target=_blank}에서 설명된 대로 문서화할 수 있습니다. +그러나 [OpenAPI에서 추가 응답](additional-responses.md)에서 설명된 대로 문서화할 수 있습니다. 이후 섹션에서 자동 데이터 변환, 문서화 등을 계속 사용하면서 이러한 사용자 정의 `Response`를 사용하는/선언하는 방법을 확인할 수 있습니다. diff --git a/docs/ko/docs/advanced/response-headers.md b/docs/ko/docs/advanced/response-headers.md index a4cb287fec..e7157d8f48 100644 --- a/docs/ko/docs/advanced/response-headers.md +++ b/docs/ko/docs/advanced/response-headers.md @@ -20,7 +20,7 @@ `Response`를 직접 반환할 때에도 헤더를 추가할 수 있습니다. -[응답을 직접 반환하기](response-directly.md){.internal-link target=_blank}에서 설명한 대로 응답을 생성하고, 헤더를 추가 매개변수로 전달하세요: +[응답을 직접 반환하기](response-directly.md)에 설명한 대로 응답을 생성하고, 헤더를 추가 매개변수로 전달하세요: {* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} @@ -36,6 +36,6 @@ ## 커스텀 헤더 { #custom-headers } -`X-` 접두어를 사용하여 커스텀 사설 헤더를 추가할 수 있다는 점을 기억하세요. +커스텀 사설 헤더는 [`X-` 접두어를 사용하여](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) 추가할 수 있다는 점을 기억하세요. -하지만, 여러분이 브라우저에서 클라이언트가 볼 수 있기를 원하는 커스텀 헤더가 있는 경우, CORS 설정에 이를 추가해야 합니다([CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}에서 자세히 알아보세요). Starlette의 CORS 문서에 문서화된 `expose_headers` 매개변수를 사용하세요. +하지만, 여러분이 브라우저에서 클라이언트가 볼 수 있기를 원하는 커스텀 헤더가 있는 경우, CORS 설정에 이를 추가해야 합니다([CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)에서 자세히 알아보세요). [Starlette의 CORS 문서](https://www.starlette.dev/middleware/#corsmiddleware)에 문서화된 `expose_headers` 매개변수를 사용하세요. diff --git a/docs/ko/docs/advanced/security/http-basic-auth.md b/docs/ko/docs/advanced/security/http-basic-auth.md index 5b50c65fda..273b802050 100644 --- a/docs/ko/docs/advanced/security/http-basic-auth.md +++ b/docs/ko/docs/advanced/security/http-basic-auth.md @@ -32,7 +32,7 @@ HTTP Basic Auth에서는 애플리케이션이 사용자명과 비밀번호가 dependency를 사용해 사용자명과 비밀번호가 올바른지 확인하세요. -이를 위해 Python 표준 모듈 `secrets`를 사용해 사용자명과 비밀번호를 확인합니다. +이를 위해 Python 표준 모듈 [`secrets`](https://docs.python.org/3/library/secrets.html)를 사용해 사용자명과 비밀번호를 확인합니다. `secrets.compare_digest()`는 `bytes` 또는 ASCII 문자(영어에서 사용하는 문자)만 포함한 `str`을 받아야 합니다. 즉, `Sebastián`의 `á` 같은 문자가 있으면 동작하지 않습니다. @@ -52,7 +52,7 @@ if not (credentials.username == "stanleyjobson") or not (credentials.password == 하지만 `secrets.compare_digest()`를 사용하면 "timing attacks"라고 불리는 한 유형의 공격에 대해 안전해집니다. -### Timing Attacks { #timing-attacks } +### 타이밍 공격 { #timing-attacks } 그렇다면 "timing attack"이란 무엇일까요? diff --git a/docs/ko/docs/advanced/security/index.md b/docs/ko/docs/advanced/security/index.md index 4c7abfacc7..126e6524a3 100644 --- a/docs/ko/docs/advanced/security/index.md +++ b/docs/ko/docs/advanced/security/index.md @@ -2,7 +2,7 @@ ## 추가 기능 { #additional-features } -[튜토리얼 - 사용자 가이드: 보안](../../tutorial/security/index.md){.internal-link target=_blank}에서 다룬 내용 외에도, 보안을 처리하기 위한 몇 가지 추가 기능이 있습니다. +[튜토리얼 - 사용자 가이드: 보안](../../tutorial/security/index.md)에서 다룬 내용 외에도, 보안을 처리하기 위한 몇 가지 추가 기능이 있습니다. /// tip | 팁 @@ -14,6 +14,6 @@ ## 먼저 튜토리얼 읽기 { #read-the-tutorial-first } -다음 섹션은 주요 [튜토리얼 - 사용자 가이드: 보안](../../tutorial/security/index.md){.internal-link target=_blank}을 이미 읽었다고 가정합니다. +다음 섹션은 주요 [튜토리얼 - 사용자 가이드: 보안](../../tutorial/security/index.md)을 이미 읽었다고 가정합니다. 모두 동일한 개념을 기반으로 하지만, 몇 가지 추가 기능을 사용할 수 있게 해줍니다. diff --git a/docs/ko/docs/advanced/security/oauth2-scopes.md b/docs/ko/docs/advanced/security/oauth2-scopes.md index 0f90f92ae9..5a785ff9fd 100644 --- a/docs/ko/docs/advanced/security/oauth2-scopes.md +++ b/docs/ko/docs/advanced/security/oauth2-scopes.md @@ -60,7 +60,7 @@ OAuth2 입장에서는 그저 문자열입니다. ## 전체 개요 { #global-view } -먼저, 메인 **튜토리얼 - 사용자 가이드**의 [비밀번호(및 해싱)를 사용하는 OAuth2, JWT 토큰을 사용하는 Bearer](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank} 예제에서 어떤 부분이 바뀌는지 빠르게 살펴보겠습니다. 이제 OAuth2 스코프를 사용합니다: +먼저, 메인 **튜토리얼 - 사용자 가이드**의 [비밀번호(및 해싱)를 사용하는 OAuth2, JWT 토큰을 사용하는 Bearer](../../tutorial/security/oauth2-jwt.md) 예제에서 어떤 부분이 바뀌는지 빠르게 살펴보겠습니다. 이제 OAuth2 스코프를 사용합니다: {* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} @@ -271,4 +271,4 @@ API 문서를 열면, 인증하고 인가할 스코프를 지정할 수 있습 ## 데코레이터 `dependencies`에서의 `Security` { #security-in-decorator-dependencies } -[경로 처리 데코레이터의 의존성](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}에서 설명한 것처럼 데코레이터의 `dependencies` 매개변수에 `Depends`의 `list`를 정의할 수 있는 것과 같은 방식으로, 거기에서 `scopes`와 함께 `Security`를 사용할 수도 있습니다. +[경로 처리 데코레이터의 의존성](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md)에서 설명한 것처럼 데코레이터의 `dependencies` 매개변수에 `Depends`의 `list`를 정의할 수 있는 것과 같은 방식으로, 거기에서 `scopes`와 함께 `Security`를 사용할 수도 있습니다. diff --git a/docs/ko/docs/advanced/settings.md b/docs/ko/docs/advanced/settings.md index f53006bfba..49a2b640e9 100644 --- a/docs/ko/docs/advanced/settings.md +++ b/docs/ko/docs/advanced/settings.md @@ -8,7 +8,7 @@ /// tip | 팁 -환경 변수를 이해하려면 [환경 변수](../environment-variables.md){.internal-link target=_blank}를 읽어보세요. +환경 변수를 이해하려면 [환경 변수](../environment-variables.md)를 읽어보세요. /// @@ -20,11 +20,11 @@ ## Pydantic `Settings` { #pydantic-settings } -다행히 Pydantic은 Pydantic: Settings management를 통해 환경 변수에서 오는 이러한 설정을 처리할 수 있는 훌륭한 유틸리티를 제공합니다. +다행히 Pydantic은 환경 변수에서 오는 이러한 설정을 처리할 수 있는 훌륭한 유틸리티를 [Pydantic: Settings 관리](https://docs.pydantic.dev/latest/concepts/pydantic_settings/)로 제공합니다. ### `pydantic-settings` 설치하기 { #install-pydantic-settings } -먼저 [가상 환경](../virtual-environments.md){.internal-link target=_blank}을 만들고 활성화한 다음, `pydantic-settings` 패키지를 설치하세요: +먼저 [가상 환경](../virtual-environments.md)을 만들고 활성화한 다음, `pydantic-settings` 패키지를 설치하세요:
@@ -100,7 +100,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p ## 다른 모듈의 설정 { #settings-in-another-module } -[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}에서 본 것처럼, 설정을 다른 모듈 파일에 넣을 수도 있습니다. +[더 큰 애플리케이션 - 여러 파일](../tutorial/bigger-applications.md)에서 본 것처럼, 설정을 다른 모듈 파일에 넣을 수도 있습니다. 예를 들어 `config.py` 파일을 다음처럼 만들 수 있습니다: @@ -112,7 +112,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p /// tip | 팁 -[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}에서 본 것처럼 `__init__.py` 파일도 필요합니다. +[더 큰 애플리케이션 - 여러 파일](../tutorial/bigger-applications.md)에서 본 것처럼 `__init__.py` 파일도 필요합니다. /// @@ -172,7 +172,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p /// -Pydantic은 외부 라이브러리를 사용해 이런 유형의 파일에서 읽는 기능을 지원합니다. 자세한 내용은 Pydantic Settings: Dotenv (.env) support를 참고하세요. +Pydantic은 외부 라이브러리를 사용해 이런 유형의 파일에서 읽는 기능을 지원합니다. 자세한 내용은 [Pydantic Settings: Dotenv (.env) 지원](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support)을 참고하세요. /// tip | 팁 @@ -197,7 +197,7 @@ APP_NAME="ChimichangApp" /// tip | 팁 -`model_config` 속성은 Pydantic 설정을 위한 것입니다. 자세한 내용은 Pydantic: Concepts: Configuration를 참고하세요. +`model_config` 속성은 Pydantic 설정을 위한 것입니다. 자세한 내용은 [Pydantic: 개념: 구성](https://docs.pydantic.dev/latest/concepts/config/)을 참고하세요. /// @@ -291,7 +291,7 @@ participant execute as Execute function 이렇게 하면 거의 전역 변수처럼 동작합니다. 하지만 의존성 함수를 사용하므로 테스트를 위해 쉽게 override할 수 있습니다. -`@lru_cache`는 Python 표준 라이브러리의 `functools`에 포함되어 있으며, 자세한 내용은 `@lru_cache`에 대한 Python 문서에서 확인할 수 있습니다. +`@lru_cache`는 Python 표준 라이브러리의 `functools`에 포함되어 있으며, 자세한 내용은 [`@lru_cache`에 대한 Python 문서](https://docs.python.org/3/library/functools.html#functools.lru_cache)에서 확인할 수 있습니다. ## 정리 { #recap } diff --git a/docs/ko/docs/advanced/sub-applications.md b/docs/ko/docs/advanced/sub-applications.md index 8da217aab6..b592c0a39d 100644 --- a/docs/ko/docs/advanced/sub-applications.md +++ b/docs/ko/docs/advanced/sub-applications.md @@ -1,10 +1,10 @@ -# 하위 응용프로그램 - 마운트 { #sub-applications-mounts } +# 하위 애플리케이션 - 마운트 { #sub-applications-mounts } -각각의 독립적인 OpenAPI와 문서 UI를 갖는 두 개의 독립적인 FastAPI 애플리케이션이 필요하다면, 메인 앱을 두고 하나(또는 그 이상)의 하위 응용프로그램을 "마운트"할 수 있습니다. +각각의 독립적인 OpenAPI와 문서 UI를 갖는 두 개의 독립적인 FastAPI 애플리케이션이 필요하다면, 메인 앱을 두고 하나(또는 그 이상)의 하위 애플리케이션을 "마운트"할 수 있습니다. ## **FastAPI** 애플리케이션 마운트 { #mounting-a-fastapi-application } -"마운트"란 완전히 "독립적인" 애플리케이션을 특정 경로에 추가하고, 그 하위 응용프로그램에 선언된 _경로 처리_로 해당 경로 아래의 모든 것을 처리하도록 하는 것을 의미합니다. +"마운트"란 완전히 "독립적인" 애플리케이션을 특정 경로에 추가하고, 그 하위 애플리케이션에 선언된 _경로 처리_로 해당 경로 아래의 모든 것을 처리하도록 하는 것을 의미합니다. ### 최상위 애플리케이션 { #top-level-application } @@ -12,17 +12,17 @@ {* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} -### 하위 응용프로그램 { #sub-application } +### 하위 애플리케이션 { #sub-application } -그 다음, 하위 응용프로그램과 그 *경로 처리*를 생성합니다. +그 다음, 하위 애플리케이션과 그 *경로 처리*를 생성합니다. -이 하위 응용프로그램은 또 다른 표준 FastAPI 애플리케이션이지만, "마운트"될 애플리케이션입니다: +이 하위 애플리케이션은 또 다른 표준 FastAPI 애플리케이션이지만, "마운트"될 애플리케이션입니다: {* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} -### 하위 응용프로그램 마운트 { #mount-the-sub-application } +### 하위 애플리케이션 마운트 { #mount-the-sub-application } -최상위 애플리케이션 `app`에서 하위 응용프로그램 `subapi`를 마운트합니다. +최상위 애플리케이션 `app`에서 하위 애플리케이션 `subapi`를 마운트합니다. 이 경우 `/subapi` 경로에 마운트됩니다: @@ -30,27 +30,27 @@ ### 자동 API 문서 확인 { #check-the-automatic-api-docs } -이제 파일과 함께 `fastapi` 명령을 실행하세요: +이제 `fastapi` 명령어를 실행하세요:
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-그리고 http://127.0.0.1:8000/docs에서 문서를 여세요. +그리고 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)에서 문서를 여세요. 메인 앱의 자동 API 문서를 보게 될 것이며, 메인 앱 자체의 _경로 처리_만 포함됩니다: -그 다음, http://127.0.0.1:8000/subapi/docs에서 하위 응용프로그램의 문서를 여세요. +그 다음, [http://127.0.0.1:8000/subapi/docs](http://127.0.0.1:8000/subapi/docs)에서 하위 애플리케이션의 문서를 여세요. -하위 응용프로그램의 자동 API 문서를 보게 될 것이며, 하위 경로 접두사 `/subapi` 아래에 올바르게 포함된 하위 응용프로그램 자체의 _경로 처리_만 포함됩니다: +하위 애플리케이션의 자동 API 문서를 보게 될 것이며, 하위 경로 접두사 `/subapi` 아래에 올바르게 포함된 하위 애플리케이션 자체의 _경로 처리_만 포함됩니다: @@ -58,10 +58,10 @@ $ fastapi dev main.py ### 기술적 세부사항: `root_path` { #technical-details-root-path } -위에서 설명한 대로 하위 응용프로그램을 마운트하면, FastAPI는 ASGI 명세의 메커니즘인 `root_path`를 사용해 하위 응용프로그램에 대한 마운트 경로를 전달하는 작업을 처리합니다. +위에서 설명한 대로 하위 애플리케이션을 마운트하면, FastAPI는 ASGI 명세의 메커니즘인 `root_path`를 사용해 하위 애플리케이션에 대한 마운트 경로를 전달하는 작업을 처리합니다. -이렇게 하면 하위 응용프로그램은 문서 UI를 위해 해당 경로 접두사를 사용해야 한다는 것을 알게 됩니다. +이렇게 하면 하위 애플리케이션은 문서 UI를 위해 해당 경로 접두사를 사용해야 한다는 것을 알게 됩니다. -또한 하위 응용프로그램도 자체적으로 하위 앱을 마운트할 수 있으며, FastAPI가 이 모든 `root_path`를 자동으로 처리하기 때문에 모든 것이 올바르게 동작합니다. +또한 하위 애플리케이션도 자체적으로 하위 앱을 마운트할 수 있으며, FastAPI가 이 모든 `root_path`를 자동으로 처리하기 때문에 모든 것이 올바르게 동작합니다. -`root_path`와 이를 명시적으로 사용하는 방법에 대해서는 [프록시 뒤](behind-a-proxy.md){.internal-link target=_blank} 섹션에서 더 알아볼 수 있습니다. +`root_path`와 이를 명시적으로 사용하는 방법에 대해서는 [프록시 뒤](behind-a-proxy.md) 섹션에서 더 알아볼 수 있습니다. diff --git a/docs/ko/docs/advanced/templates.md b/docs/ko/docs/advanced/templates.md index 3ae718f153..9c33f37e91 100644 --- a/docs/ko/docs/advanced/templates.md +++ b/docs/ko/docs/advanced/templates.md @@ -8,7 +8,7 @@ ## 의존성 설치 { #install-dependencies } -[가상 환경](../virtual-environments.md){.internal-link target=_blank}을 생성하고, 활성화한 후 `jinja2`를 설치해야 합니다: +[가상 환경](../virtual-environments.md)을 생성하고, 활성화한 후 `jinja2`를 설치해야 합니다:
@@ -123,4 +123,4 @@ Item ID: 42 ## 더 많은 세부 사항 { #more-details } -템플릿 테스트를 포함한 더 많은 세부 사항은 Starlette의 템플릿 문서를 확인하세요. +템플릿 테스트를 포함한 더 많은 세부 사항은 [Starlette의 템플릿 문서](https://www.starlette.dev/templates/)를 확인하세요. diff --git a/docs/ko/docs/advanced/testing-websockets.md b/docs/ko/docs/advanced/testing-websockets.md index 23ff34cd3a..28f131c2d1 100644 --- a/docs/ko/docs/advanced/testing-websockets.md +++ b/docs/ko/docs/advanced/testing-websockets.md @@ -6,8 +6,8 @@ {* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} -/// note | 참고 +/// note -자세한 내용은 Starlette의 WebSocket 테스트 문서를 확인하세요. +자세한 내용은 Starlette의 [WebSocket 테스트](https://www.starlette.dev/testclient/#testing-websocket-sessions) 문서를 확인하세요. /// diff --git a/docs/ko/docs/advanced/using-request-directly.md b/docs/ko/docs/advanced/using-request-directly.md index 0c45e2e2f8..7456d2a79c 100644 --- a/docs/ko/docs/advanced/using-request-directly.md +++ b/docs/ko/docs/advanced/using-request-directly.md @@ -15,7 +15,7 @@ ## `Request` 객체에 대한 세부 사항 { #details-about-the-request-object } -**FastAPI**는 실제로 내부에 **Starlette**을 사용하며, 그 위에 여러 도구를 덧붙인 구조입니다. 따라서 여러분이 필요할 때 Starlette의 `Request` 객체를 직접 사용할 수 있습니다. +**FastAPI**는 실제로 내부에 **Starlette**을 사용하며, 그 위에 여러 도구를 덧붙인 구조입니다. 따라서 여러분이 필요할 때 Starlette의 [`Request`](https://www.starlette.dev/requests/) 객체를 직접 사용할 수 있습니다. 또한 이는 `Request` 객체에서 데이터를 직접 가져오는 경우(예: 본문을 읽기) FastAPI가 해당 데이터를 검증하거나 변환하지 않으며, 문서화(OpenAPI를 통한 자동 API 사용자 인터페이스용)도 되지 않는다는 의미이기도 합니다. @@ -45,7 +45,7 @@ ## `Request` 설명서 { #request-documentation } -여러분은 공식 Starlette 설명서 사이트의 `Request` 객체에 대한 더 자세한 내용을 읽어볼 수 있습니다. +여러분은 [`Request` 객체에 대한 공식 Starlette 설명서 사이트](https://www.starlette.dev/requests/)에 대한 더 자세한 내용을 읽어볼 수 있습니다. /// note | 기술 세부사항 diff --git a/docs/ko/docs/advanced/websockets.md b/docs/ko/docs/advanced/websockets.md index cb59097f6e..0b920c3b38 100644 --- a/docs/ko/docs/advanced/websockets.md +++ b/docs/ko/docs/advanced/websockets.md @@ -1,10 +1,10 @@ # WebSockets { #websockets } -여러분은 **FastAPI**에서 WebSockets를 사용할 수 있습니다. +여러분은 **FastAPI**에서 [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)를 사용할 수 있습니다. ## `websockets` 설치 { #install-websockets } -[가상 환경](../virtual-environments.md){.internal-link target=_blank}을 생성하고 활성화한 다음, `websockets`("WebSocket" 프로토콜을 쉽게 사용할 수 있게 해주는 Python 라이브러리)를 설치하세요: +[가상 환경](../virtual-environments.md)을 생성하고 활성화한 다음, `websockets`("WebSocket" 프로토콜을 쉽게 사용할 수 있게 해주는 Python 라이브러리)를 설치하세요:
@@ -64,19 +64,19 @@ WebSocket 경로에서 메시지를 대기(`await`)하고 전송할 수 있습 ## 시도해보기 { #try-it } -파일 이름이 `main.py`라고 가정하고 다음으로 애플리케이션을 실행합니다: +코드를 `main.py` 파일에 넣고 애플리케이션을 실행합니다:
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-브라우저에서 http://127.0.0.1:8000을 여세요. +브라우저에서 [http://127.0.0.1:8000](http://127.0.0.1:8000)을 여세요. 간단한 페이지가 나타날 것입니다: @@ -115,25 +115,25 @@ WebSocket 엔드포인트에서 `fastapi`에서 다음을 가져와 사용할 WebSocket이기 때문에 `HTTPException`을 발생시키는 것은 적절하지 않습니다. 대신 `WebSocketException`을 발생시킵니다. -명세서에 정의된 유효한 코드를 사용하여 종료 코드를 설정할 수 있습니다. +명세서에 정의된 [유효한 코드](https://tools.ietf.org/html/rfc6455#section-7.4.1)를 사용하여 종료 코드를 설정할 수 있습니다. /// ### 종속성을 가진 WebSockets 시도해보기 { #try-the-websockets-with-dependencies } -파일 이름이 `main.py`라고 가정하고 다음으로 애플리케이션을 실행합니다: +애플리케이션을 실행합니다:
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-브라우저에서 http://127.0.0.1:8000을 여세요. +브라우저에서 [http://127.0.0.1:8000](http://127.0.0.1:8000)을 여세요. 여기에서 다음을 설정할 수 있습니다: @@ -174,7 +174,7 @@ Client #1596980209979 left the chat 하지만 모든 것을 메모리의 단일 리스트로 처리하므로, 프로세스가 실행 중인 동안만 동작하며 단일 프로세스에서만 작동한다는 점을 기억하세요. -FastAPI와 쉽게 통합할 수 있으면서 더 견고하고 Redis, PostgreSQL 등을 지원하는 도구가 필요하다면, encode/broadcaster를 확인하세요. +FastAPI와 쉽게 통합할 수 있으면서 더 견고하고 Redis, PostgreSQL 등을 지원하는 도구가 필요하다면, [encode/broadcaster](https://github.com/encode/broadcaster)를 확인하세요. /// @@ -182,5 +182,5 @@ FastAPI와 쉽게 통합할 수 있으면서 더 견고하고 Redis, PostgreSQL 다음 옵션에 대해 더 알아보려면 Starlette의 문서를 확인하세요: -* `WebSocket` 클래스. -* 클래스 기반 WebSocket 처리. +* [`WebSocket` 클래스](https://www.starlette.dev/websockets/). +* [클래스 기반 WebSocket 처리](https://www.starlette.dev/endpoints/#websocketendpoint). diff --git a/docs/ko/docs/advanced/wsgi.md b/docs/ko/docs/advanced/wsgi.md index 24b074443d..921e426efd 100644 --- a/docs/ko/docs/advanced/wsgi.md +++ b/docs/ko/docs/advanced/wsgi.md @@ -1,6 +1,6 @@ # WSGI 포함하기 - Flask, Django 등 { #including-wsgi-flask-django-others } -[서브 애플리케이션 - 마운트](sub-applications.md){.internal-link target=_blank}, [프록시 뒤에서](behind-a-proxy.md){.internal-link target=_blank}에서 본 것처럼 WSGI 애플리케이션을 마운트할 수 있습니다. +[서브 애플리케이션 - 마운트](sub-applications.md), [프록시 뒤에서](behind-a-proxy.md)에서 본 것처럼 WSGI 애플리케이션을 마운트할 수 있습니다. 이를 위해 `WSGIMiddleware`를 사용해 WSGI 애플리케이션(예: Flask, Django 등)을 감쌀 수 있습니다. @@ -36,13 +36,13 @@ 그리고 나머지는 **FastAPI**에 의해 처리됩니다. -실행하고 http://localhost:8000/v1/로 이동하면 Flask의 응답을 볼 수 있습니다: +실행하고 [http://localhost:8000/v1/](http://localhost:8000/v1/)로 이동하면 Flask의 응답을 볼 수 있습니다: ```txt Hello, World from Flask! ``` -그리고 http://localhost:8000/v2로 이동하면 **FastAPI**의 응답을 볼 수 있습니다: +그리고 [http://localhost:8000/v2](http://localhost:8000/v2)로 이동하면 **FastAPI**의 응답을 볼 수 있습니다: ```JSON { diff --git a/docs/ko/docs/alternatives.md b/docs/ko/docs/alternatives.md index f26fbe39dd..4f92f69d24 100644 --- a/docs/ko/docs/alternatives.md +++ b/docs/ko/docs/alternatives.md @@ -14,7 +14,7 @@ ## 이전 도구들 { #previous-tools } -### Django { #django } +### [Django](https://www.djangoproject.com/) { #django } 가장 인기 있는 Python framework이며 널리 신뢰받고 있습니다. Instagram 같은 시스템을 만드는 데 사용됩니다. @@ -22,7 +22,7 @@ 백엔드에서 HTML을 생성하기 위해 만들어졌지, 현대적인 프런트엔드(예: React, Vue.js, Angular)나 다른 시스템(예: IoT 기기)에서 사용되는 API를 만들기 위해 설계된 것은 아닙니다. -### Django REST Framework { #django-rest-framework } +### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } Django REST framework는 Django를 기반으로 Web API를 구축하기 위한 유연한 toolkit으로 만들어졌고, Django의 API 기능을 개선하기 위한 목적이었습니다. @@ -42,7 +42,7 @@ Django REST Framework는 Tom Christie가 만들었습니다. **FastAPI**의 기 /// -### Flask { #flask } +### [Flask](https://flask.palletsprojects.com) { #flask } Flask는 "microframework"로, Django에 기본으로 포함된 데이터베이스 통합이나 여러 기능들을 포함하지 않습니다. @@ -64,7 +64,7 @@ micro-framework가 되기. 필요한 도구와 구성요소를 쉽게 조합할 /// -### Requests { #requests } +### [Requests](https://requests.readthedocs.io) { #requests } **FastAPI**는 실제로 **Requests**의 대안이 아닙니다. 둘의 범위는 매우 다릅니다. @@ -106,7 +106,7 @@ def read_url(): /// -### Swagger / OpenAPI { #swagger-openapi } +### [Swagger](https://swagger.io/) / [OpenAPI](https://github.com/OAI/OpenAPI-Specification/) { #swagger-openapi } 제가 Django REST Framework에서 가장 원했던 주요 기능은 자동 API 문서화였습니다. @@ -124,8 +124,8 @@ def read_url(): 또한 표준 기반의 사용자 인터페이스 도구를 통합하기: -* Swagger UI -* ReDoc +* [Swagger UI](https://github.com/swagger-api/swagger-ui) +* [ReDoc](https://github.com/Rebilly/ReDoc) 이 두 가지는 꽤 대중적이고 안정적이기 때문에 선택되었습니다. 하지만 간단히 검색해보면 OpenAPI를 위한 대안 UI가 수십 가지나 있다는 것을 알 수 있습니다(**FastAPI**와 함께 사용할 수 있습니다). @@ -135,7 +135,7 @@ def read_url(): Flask REST framework는 여러 개가 있지만, 시간을 들여 조사해 본 결과, 상당수가 중단되었거나 방치되어 있었고, 해결되지 않은 여러 이슈 때문에 적합하지 않은 경우가 많았습니다. -### Marshmallow { #marshmallow } +### [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) { #marshmallow } API 시스템에 필요한 주요 기능 중 하나는 데이터 "직렬화"입니다. 이는 코드(Python)에서 데이터를 가져와 네트워크로 전송할 수 있는 형태로 변환하는 것을 의미합니다. 예를 들어 데이터베이스의 데이터를 담은 객체를 JSON 객체로 변환하거나, `datetime` 객체를 문자열로 변환하는 등의 작업입니다. @@ -153,7 +153,7 @@ API에 또 하나 크게 필요한 기능은 데이터 검증입니다. 특정 /// -### Webargs { #webargs } +### [Webargs](https://webargs.readthedocs.io/en/latest/) { #webargs } API에 필요한 또 다른 큰 기능은 들어오는 요청에서 데이터를 파싱하는 것입니다. @@ -175,7 +175,7 @@ Webargs는 Marshmallow와 같은 개발자들이 만들었습니다. /// -### APISpec { #apispec } +### [APISpec](https://apispec.readthedocs.io/en/stable/) { #apispec } Marshmallow와 Webargs는 plug-in 형태로 검증, parsing, serialization을 제공합니다. @@ -205,7 +205,7 @@ API를 위한 열린 표준인 OpenAPI를 지원하기. /// -### Flask-apispec { #flask-apispec } +### [Flask-apispec](https://flask-apispec.readthedocs.io/en/latest/) { #flask-apispec } Flask plug-in으로, Webargs, Marshmallow, APISpec을 묶어줍니다. @@ -219,11 +219,11 @@ Flask + Flask-apispec + Marshmallow + Webargs 조합은 **FastAPI**를 만들기 이를 사용하면서 여러 Flask full-stack generator가 만들어졌습니다. 이것들이 지금까지 저(그리고 여러 외부 팀)가 사용해 온 주요 stack입니다: -* https://github.com/tiangolo/full-stack -* https://github.com/tiangolo/full-stack-flask-couchbase -* https://github.com/tiangolo/full-stack-flask-couchdb +* [https://github.com/tiangolo/full-stack](https://github.com/tiangolo/full-stack) +* [https://github.com/tiangolo/full-stack-flask-couchbase](https://github.com/tiangolo/full-stack-flask-couchbase) +* [https://github.com/tiangolo/full-stack-flask-couchdb](https://github.com/tiangolo/full-stack-flask-couchdb) -그리고 이 동일한 full-stack generator들이 [**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}의 기반이 되었습니다. +그리고 이 동일한 full-stack generator들이 [**FastAPI** Project Generators](project-generation.md)의 기반이 되었습니다. /// info | 정보 @@ -237,7 +237,7 @@ serialization과 validation을 정의하는 동일한 코드로부터 OpenAPI sc /// -### NestJS (그리고 Angular) { #nestjs-and-angular } +### [NestJS](https://nestjs.com/) (그리고 [Angular](https://angular.io/)) { #nestjs-and-angular } 이건 Python도 아닙니다. NestJS는 Angular에서 영감을 받은 JavaScript(TypeScript) NodeJS framework입니다. @@ -259,13 +259,13 @@ Python 타입을 사용해 뛰어난 에디터 지원을 제공하기. /// -### Sanic { #sanic } +### [Sanic](https://sanic.readthedocs.io/en/latest/) { #sanic } `asyncio` 기반의 매우 빠른 Python framework 중 초기 사례였습니다. Flask와 매우 유사하게 만들어졌습니다. /// note | 기술 세부사항 -기본 Python `asyncio` 루프 대신 `uvloop`를 사용했습니다. 이것이 매우 빠르게 만든 요인입니다. +[`uvloop`](https://github.com/MagicStack/uvloop)를 기본 Python `asyncio` 루프 대신 사용했습니다. 이것이 매우 빠르게 만든 요인입니다. 이는 Uvicorn과 Starlette에 명확히 영감을 주었고, 현재 공개 benchmark에서는 이 둘이 Sanic보다 더 빠릅니다. @@ -279,7 +279,7 @@ Python 타입을 사용해 뛰어난 에디터 지원을 제공하기. /// -### Falcon { #falcon } +### [Falcon](https://falconframework.org/) { #falcon } Falcon은 또 다른 고성능 Python framework로, 최소한으로 설계되었고 Hug 같은 다른 framework의 기반으로 동작하도록 만들어졌습니다. @@ -297,7 +297,7 @@ Hug(= Falcon 기반)과 함께, 함수에서 `response` 파라미터를 선언 /// -### Molten { #molten } +### [Molten](https://moltenframework.com/) { #molten } **FastAPI**를 만들기 시작한 초기 단계에서 Molten을 알게 되었고, 꽤 비슷한 아이디어를 갖고 있었습니다: @@ -321,7 +321,7 @@ Route는 한 곳에서 선언하고, 다른 곳에 선언된 함수를 사용합 /// -### Hug { #hug } +### [Hug](https://github.com/hugapi/hug) { #hug } Hug는 Python type hints를 사용해 API 파라미터 타입을 선언하는 기능을 구현한 초기 framework 중 하나였습니다. 이는 다른 도구들도 같은 방식을 하도록 영감을 준 훌륭한 아이디어였습니다. @@ -337,7 +337,7 @@ OpenAPI나 JSON Schema 같은 표준을 기반으로 하지 않았기 때문에 /// info | 정보 -Hug는 Timothy Crosley가 만들었습니다. Python 파일에서 import를 자동으로 정렬하는 훌륭한 도구인 `isort`의 제작자이기도 합니다. +Hug는 Timothy Crosley가 만들었습니다. Python 파일에서 import를 자동으로 정렬하는 훌륭한 도구인 [`isort`](https://github.com/timothycrosley/isort)의 제작자이기도 합니다. /// @@ -351,7 +351,7 @@ Hug는 헤더와 쿠키를 설정하기 위해 함수에 `response` 파라미터 /// -### APIStar (<= 0.5) { #apistar-0-5 } +### [APIStar](https://github.com/encode/apistar) (<= 0.5) { #apistar-0-5 } **FastAPI**를 만들기로 결정하기 직전에 **APIStar** 서버를 발견했습니다. 찾고 있던 거의 모든 것을 갖추고 있었고 설계도 훌륭했습니다. @@ -401,7 +401,7 @@ APIStar는 Tom Christie가 만들었습니다. 다음을 만든 사람과 동일 ## **FastAPI**가 사용하는 것 { #used-by-fastapi } -### Pydantic { #pydantic } +### [Pydantic](https://docs.pydantic.dev/) { #pydantic } Pydantic은 Python type hints를 기반으로 데이터 검증, serialization, 문서화(JSON Schema 사용)를 정의하는 라이브러리입니다. @@ -417,7 +417,7 @@ Marshmallow와 비교할 수 있습니다. 다만 benchmark에서 Marshmallow보 /// -### Starlette { #starlette } +### [Starlette](https://www.starlette.dev/) { #starlette } Starlette는 경량 ASGI framework/toolkit으로, 고성능 asyncio 서비스를 만들기에 이상적입니다. @@ -462,7 +462,7 @@ ASGI는 Django 코어 팀 멤버들이 개발 중인 새로운 "표준"입니다 /// -### Uvicorn { #uvicorn } +### [Uvicorn](https://www.uvicorn.dev/) { #uvicorn } Uvicorn은 uvloop과 httptools로 구축된 초고속 ASGI 서버입니다. @@ -476,10 +476,10 @@ Starlette와 **FastAPI**에서 권장하는 서버입니다. 또한 `--workers` 커맨드라인 옵션을 사용하면 비동기 멀티프로세스 서버로 실행할 수도 있습니다. -자세한 내용은 [배포](deployment/index.md){.internal-link target=_blank} 섹션을 확인하세요. +자세한 내용은 [배포](deployment/index.md) 섹션을 확인하세요. /// ## 벤치마크와 속도 { #benchmarks-and-speed } -Uvicorn, Starlette, FastAPI 사이의 차이를 이해하고 비교하려면 [벤치마크](benchmarks.md){.internal-link target=_blank} 섹션을 확인하세요. +Uvicorn, Starlette, FastAPI 사이의 차이를 이해하고 비교하려면 [벤치마크](benchmarks.md) 섹션을 확인하세요. diff --git a/docs/ko/docs/async.md b/docs/ko/docs/async.md index 36f1ca6bf1..485111fac9 100644 --- a/docs/ko/docs/async.md +++ b/docs/ko/docs/async.md @@ -141,7 +141,7 @@ def results(): /// info | 정보 -아름다운 일러스트: Ketrina Thompson. 🎨 +아름다운 일러스트: [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 /// @@ -207,7 +207,7 @@ def results(): /// info | 정보 -아름다운 일러스트: Ketrina Thompson. 🎨 +아름다운 일러스트: [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 /// @@ -251,7 +251,7 @@ def results(): 그리고 이것이 **FastAPI**로 얻는 것과 같은 수준의 성능입니다. -또한 병렬성과 비동기성을 동시에 사용할 수 있으므로, 대부분의 테스트된 NodeJS 프레임워크보다 더 높은 성능을 얻고, C에 더 가까운 컴파일 언어인 Go와 동등한 성능을 얻을 수 있습니다 (모두 Starlette 덕분입니다). +또한 병렬성과 비동기성을 동시에 사용할 수 있으므로, 대부분의 테스트된 NodeJS 프레임워크보다 더 높은 성능을 얻고, C에 더 가까운 컴파일 언어인 Go와 동등한 성능을 얻을 수 있습니다 [(모두 Starlette 덕분입니다)](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1). ### 동시성이 병렬성보다 더 나은가요? { #is-concurrency-better-than-parallelism } @@ -298,7 +298,7 @@ CPU bound 작업의 흔한 예시는 복잡한 수학 처리가 필요한 것들 이것은 파이썬이 **데이터 사이언스**, 머신러닝, 특히 딥러닝의 주요 언어라는 단순한 사실과 더해져, FastAPI를 데이터 사이언스/머신러닝 웹 API 및 애플리케이션(그 외에도 많은 것들)에 매우 잘 맞는 선택으로 만들어 줍니다. -프로덕션에서 이 병렬성을 어떻게 달성하는지 보려면 [배포](deployment/index.md){.internal-link target=_blank} 섹션을 참고하세요. +프로덕션에서 이 병렬성을 어떻게 달성하는지 보려면 [배포](deployment/index.md) 섹션을 참고하세요. ## `async`와 `await` { #async-and-await } @@ -363,13 +363,13 @@ async def read_burgers(): ### 여러분만의 async 코드 작성하기 { #write-your-own-async-code } -Starlette(그리고 **FastAPI**)는 AnyIO를 기반으로 하고 있으며, 파이썬 표준 라이브러리 asyncioTrio 모두와 호환됩니다. +Starlette(그리고 **FastAPI**)는 [AnyIO](https://anyio.readthedocs.io/en/stable/)를 기반으로 하고 있으며, 파이썬 표준 라이브러리 [asyncio](https://docs.python.org/3/library/asyncio-task.html)와 [Trio](https://trio.readthedocs.io/en/stable/) 모두와 호환됩니다. -특히, 코드에서 더 고급 패턴이 필요한 고급 동시성 사용 사례에서는 직접 AnyIO를 사용할 수 있습니다. +특히, 코드에서 더 고급 패턴이 필요한 고급 동시성 사용 사례에서는 직접 [AnyIO](https://anyio.readthedocs.io/en/stable/)를 사용할 수 있습니다. -그리고 FastAPI를 사용하지 않더라도, 높은 호환성을 확보하고 그 이점(예: *structured concurrency*)을 얻기 위해 AnyIO로 여러분만의 async 애플리케이션을 작성할 수도 있습니다. +그리고 FastAPI를 사용하지 않더라도, 높은 호환성을 확보하고 그 이점(예: *structured concurrency*)을 얻기 위해 [AnyIO](https://anyio.readthedocs.io/en/stable/)로 여러분만의 async 애플리케이션을 작성할 수도 있습니다. -저는 AnyIO 위에 얇은 레이어로 또 다른 라이브러리를 만들었는데, 타입 어노테이션을 조금 개선하고 더 나은 **자동완성**, **인라인 오류** 등을 얻기 위한 것입니다. 또한 **이해**하고 **여러분만의 async 코드**를 작성하도록 돕는 친절한 소개와 튜토리얼도 제공합니다: Asyncer. 특히 **async 코드와 일반**(blocking/동기) 코드를 **결합**해야 한다면 아주 유용합니다. +저는 AnyIO 위에 얇은 레이어로 또 다른 라이브러리를 만들었는데, 타입 어노테이션을 조금 개선하고 더 나은 **자동완성**, **인라인 오류** 등을 얻기 위한 것입니다. 또한 **이해**하고 **여러분만의 async 코드**를 작성하도록 돕는 친절한 소개와 튜토리얼도 제공합니다: [Asyncer](https://asyncer.tiangolo.com/). 특히 **async 코드와 일반**(blocking/동기) 코드를 **결합**해야 한다면 아주 유용합니다. ### 비동기 코드의 다른 형태 { #other-forms-of-asynchronous-code } @@ -381,7 +381,7 @@ Starlette(그리고 **FastAPI**)는 Gevent를 사용할 수 있었을 것입니다. 하지만 코드를 이해하고, 디버깅하고, 이에 대해 생각하는 것이 훨씬 더 복잡합니다. +이전 버전의 파이썬에서는 스레드 또는 [Gevent](https://www.gevent.org/)를 사용할 수 있었을 것입니다. 하지만 코드를 이해하고, 디버깅하고, 이에 대해 생각하는 것이 훨씬 더 복잡합니다. 이전 버전의 NodeJS/브라우저 JavaScript에서는 "callback"을 사용했을 것입니다. 이는 "callback hell"로 이어집니다. @@ -419,15 +419,15 @@ Starlette(그리고 **FastAPI**)는 I/O 를 수행하는 코드를 사용하지 않는 한 `async def`를 사용하는 편이 더 낫습니다. -그럼에도 두 경우 모두, **FastAPI**는 이전에 사용하던 프레임워크보다 [여전히 더 빠를](index.md#performance){.internal-link target=_blank} 가능성이 높습니다(또는 최소한 비슷합니다). +그럼에도 두 경우 모두, **FastAPI**는 이전에 사용하던 프레임워크보다 [여전히 더 빠를](index.md#performance) 가능성이 높습니다(또는 최소한 비슷합니다). ### 의존성 { #dependencies } -[의존성](tutorial/dependencies/index.md){.internal-link target=_blank}에도 동일하게 적용됩니다. 의존성이 `async def` 대신 표준 `def` 함수라면, 외부 스레드풀에서 실행됩니다. +[의존성](tutorial/dependencies/index.md)에도 동일하게 적용됩니다. 의존성이 `async def` 대신 표준 `def` 함수라면, 외부 스레드풀에서 실행됩니다. ### 하위 의존성 { #sub-dependencies } -서로를 필요로 하는 여러 의존성과 [하위 의존성](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank}을 함수 정의의 매개변수로 가질 수 있으며, 그중 일부는 `async def`로, 다른 일부는 일반 `def`로 생성되었을 수 있습니다. 그래도 정상 동작하며, 일반 `def`로 생성된 것들은 "await"되는 대신 (스레드풀에서) 외부 스레드에서 호출됩니다. +서로를 필요로 하는 여러 의존성과 [하위 의존성](tutorial/dependencies/sub-dependencies.md)을 함수 정의의 매개변수로 가질 수 있으며, 그중 일부는 `async def`로, 다른 일부는 일반 `def`로 생성되었을 수 있습니다. 그래도 정상 동작하며, 일반 `def`로 생성된 것들은 "await"되는 대신 (스레드풀에서) 외부 스레드에서 호출됩니다. ### 다른 유틸리티 함수 { #other-utility-functions } diff --git a/docs/ko/docs/benchmarks.md b/docs/ko/docs/benchmarks.md index 2d4fdbeddb..43c25e865f 100644 --- a/docs/ko/docs/benchmarks.md +++ b/docs/ko/docs/benchmarks.md @@ -1,6 +1,6 @@ # 벤치마크 { #benchmarks } -독립적인 TechEmpower 벤치마크에 따르면 **FastAPI** 애플리케이션이 Uvicorn을 사용하여 사용 가능한 가장 빠른 Python 프레임워크 중 하나로 실행되며, Starlette와 Uvicorn 자체(내부적으로 FastAPI가 사용하는 도구)보다 조금 아래에 위치합니다. +독립적인 TechEmpower 벤치마크에 따르면 **FastAPI** 애플리케이션이 Uvicorn을 사용하여 [사용 가능한 가장 빠른 Python 프레임워크 중 하나](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7)로 실행되며, Starlette와 Uvicorn 자체(내부적으로 FastAPI가 사용하는 도구)보다 조금 아래에 위치합니다. 그러나 벤치마크와 비교를 확인할 때 다음 사항을 염두에 두어야 합니다. diff --git a/docs/ko/docs/deployment/cloud.md b/docs/ko/docs/deployment/cloud.md index 0705e120c4..9d9dc93a3d 100644 --- a/docs/ko/docs/deployment/cloud.md +++ b/docs/ko/docs/deployment/cloud.md @@ -6,7 +6,7 @@ ## FastAPI Cloud { #fastapi-cloud } -**FastAPI Cloud**는 **FastAPI**를 만든 동일한 작성자와 팀이 구축했습니다. +**[FastAPI Cloud](https://fastapicloud.com)**는 **FastAPI**를 만든 동일한 작성자와 팀이 구축했습니다. 최소한의 노력으로 API를 **구축**, **배포**, **접근**하는 과정을 간소화합니다. @@ -16,9 +16,9 @@ FastAPI Cloud는 *FastAPI and friends* 오픈 소스 프로젝트의 주요 후 ## 클라우드 제공업체 - 후원자들 { #cloud-providers-sponsors } -다른 몇몇 클라우드 제공업체들도 ✨ [**FastAPI를 후원합니다**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨. 🙇 +다른 몇몇 클라우드 제공업체들도 ✨ [**FastAPI를 후원합니다**](../help-fastapi.md#sponsor-the-author) ✨. 🙇 가이드를 따라 하고 서비스를 사용해보기 위해 이들도 고려해볼 수 있습니다: -* Render -* Railway +* [Render](https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi) +* [Railway](https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi) diff --git a/docs/ko/docs/deployment/concepts.md b/docs/ko/docs/deployment/concepts.md index dd7edd1bae..a5c5e53e0d 100644 --- a/docs/ko/docs/deployment/concepts.md +++ b/docs/ko/docs/deployment/concepts.md @@ -25,7 +25,7 @@ ## 보안 - HTTPS { #security-https } -[이전 HTTPS 장](https.md){.internal-link target=_blank}에서 HTTPS가 API에 암호화를 제공하는 방식에 대해 배웠습니다. +[이전 HTTPS 장](https.md)에서 HTTPS가 API에 암호화를 제공하는 방식에 대해 배웠습니다. 또한 HTTPS는 일반적으로 애플리케이션 서버 바깥의 **외부** 컴포넌트인 **TLS Termination Proxy**가 제공한다는 것도 확인했습니다. @@ -190,7 +190,7 @@ FastAPI 애플리케이션은 Uvicorn을 실행하는 `fastapi` 명령 같은 ### 워커 프로세스와 포트 { #worker-processes-and-ports } -[HTTPS에 대한 문서](https.md){.internal-link target=_blank}에서, 서버에서 하나의 포트와 IP 주소 조합에는 하나의 프로세스만 리스닝할 수 있다는 것을 기억하시나요? +[HTTPS에 대한 문서](https.md)에서, 서버에서 하나의 포트와 IP 주소 조합에는 하나의 프로세스만 리스닝할 수 있다는 것을 기억하시나요? 이것은 여전히 사실입니다. @@ -243,7 +243,7 @@ FastAPI 애플리케이션은 Uvicorn을 실행하는 `fastapi` 명령 같은 **컨테이너**, Docker, Kubernetes에 대한 일부 내용이 아직은 잘 이해되지 않아도 괜찮습니다. -다음 장에서 컨테이너 이미지, Docker, Kubernetes 등을 더 설명하겠습니다: [컨테이너에서 FastAPI - Docker](docker.md){.internal-link target=_blank}. +다음 장에서 컨테이너 이미지, Docker, Kubernetes 등을 더 설명하겠습니다: [컨테이너에서 FastAPI - Docker](docker.md). /// @@ -281,7 +281,7 @@ FastAPI 애플리케이션은 Uvicorn을 실행하는 `fastapi` 명령 같은 /// tip | 팁 -컨테이너로 이를 처리하는 더 구체적인 예시는 다음 장에서 제공하겠습니다: [컨테이너에서 FastAPI - Docker](docker.md){.internal-link target=_blank}. +컨테이너로 이를 처리하는 더 구체적인 예시는 다음 장에서 제공하겠습니다: [컨테이너에서 FastAPI - Docker](docker.md). /// diff --git a/docs/ko/docs/deployment/docker.md b/docs/ko/docs/deployment/docker.md index ca0136d836..d965af1d1e 100644 --- a/docs/ko/docs/deployment/docker.md +++ b/docs/ko/docs/deployment/docker.md @@ -1,6 +1,6 @@ # 컨테이너의 FastAPI - 도커 { #fastapi-in-containers-docker } -FastAPI 애플리케이션을 배포할 때 일반적인 접근 방법은 **리눅스 컨테이너 이미지**를 빌드하는 것입니다. 보통 **Docker**를 사용해 수행합니다. 그런 다음 해당 컨테이너 이미지를 몇 가지 가능한 방법 중 하나로 배포할 수 있습니다. +FastAPI 애플리케이션을 배포할 때 일반적인 접근 방법은 **리눅스 컨테이너 이미지**를 빌드하는 것입니다. 보통 [**Docker**](https://www.docker.com/)를 사용해 수행합니다. 그런 다음 해당 컨테이너 이미지를 몇 가지 가능한 방법 중 하나로 배포할 수 있습니다. 리눅스 컨테이너를 사용하면 **보안**, **재현 가능성**, **단순함** 등 여러 장점이 있습니다. @@ -60,16 +60,16 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] Docker는 **컨테이너 이미지**와 **컨테이너**를 생성하고 관리하는 주요 도구 중 하나입니다. -또한 Docker Hub에는 다양한 도구, 환경, 데이터베이스, 애플리케이션을 위한 미리 만들어진 **공식 컨테이너 이미지**가 공개되어 있습니다. +또한 [Docker Hub](https://hub.docker.com/)에는 다양한 도구, 환경, 데이터베이스, 애플리케이션을 위한 미리 만들어진 **공식 컨테이너 이미지**가 공개되어 있습니다. -예를 들어, 공식 Python Image가 있습니다. +예를 들어, 공식 [Python Image](https://hub.docker.com/_/python)가 있습니다. 그리고 데이터베이스 등 다양한 용도의 다른 이미지도 많이 있습니다. 예를 들면: -* PostgreSQL -* MySQL -* MongoDB -* Redis 등 +* [PostgreSQL](https://hub.docker.com/_/postgres) +* [MySQL](https://hub.docker.com/_/mysql) +* [MongoDB](https://hub.docker.com/_/mongo) +* [Redis](https://hub.docker.com/_/redis) 등 미리 만들어진 컨테이너 이미지를 사용하면 서로 다른 도구를 **결합**하고 사용하기가 매우 쉽습니다. 예를 들어 새로운 데이터베이스를 시험해 볼 때도 그렇습니다. 대부분의 경우 **공식 이미지**를 사용하고, 환경 변수로 설정만 하면 됩니다. @@ -111,7 +111,7 @@ Docker나 Kubernetes 같은 모든 컨테이너 관리 시스템에는 이러한 가장 일반적인 방법은 패키지 이름과 버전을 한 줄에 하나씩 적어 둔 `requirements.txt` 파일을 사용하는 것입니다. -버전 범위를 설정할 때는 [FastAPI 버전들에 대하여](versions.md){.internal-link target=_blank}에서 읽은 것과 같은 아이디어를 사용하면 됩니다. +버전 범위를 설정할 때는 [FastAPI 버전들에 대하여](versions.md)에서 읽은 것과 같은 아이디어를 사용하면 됩니다. 예를 들어 `requirements.txt`는 다음과 같을 수 있습니다: @@ -238,7 +238,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] #### `CMD` 사용하기 - Exec Form { #use-cmd-exec-form } -Docker 지시어 `CMD`는 두 가지 형식으로 작성할 수 있습니다: +Docker 지시어 [`CMD`](https://docs.docker.com/reference/dockerfile/#cmd)는 두 가지 형식으로 작성할 수 있습니다: ✅ **Exec** form: @@ -254,11 +254,11 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] CMD fastapi run app/main.py --port 80 ``` -FastAPI가 정상적으로 종료(graceful shutdown)되고 [lifespan 이벤트](../advanced/events.md){.internal-link target=_blank}가 트리거되도록 하려면, 항상 **exec** form을 사용하세요. +FastAPI가 정상적으로 종료(graceful shutdown)되고 [lifespan 이벤트](../advanced/events.md)가 트리거되도록 하려면, 항상 **exec** form을 사용하세요. -자세한 내용은 shell and exec form에 대한 Docker 문서를 참고하세요. +자세한 내용은 [shell and exec form에 대한 Docker 문서](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form)를 참고하세요. -이는 `docker compose`를 사용할 때 꽤 눈에 띌 수 있습니다. 좀 더 기술적인 상세 내용은 Docker Compose FAQ 섹션을 참고하세요: Why do my services take 10 seconds to recreate or stop?. +이는 `docker compose`를 사용할 때 꽤 눈에 띌 수 있습니다. 좀 더 기술적인 상세 내용은 Docker Compose FAQ 섹션을 참고하세요: [Why do my services take 10 seconds to recreate or stop?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop). #### 디렉터리 구조 { #directory-structure } @@ -305,7 +305,7 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt 패키지 의존성을 다운로드하고 설치하는 데에는 **몇 분**이 걸릴 수 있지만, **캐시**를 사용하면 많아야 **몇 초**면 끝납니다. -또한 개발 중에 코드 변경 사항이 동작하는지 확인하기 위해 컨테이너 이미지를 계속 빌드하게 되므로, 이렇게 절약되는 시간은 누적되어 상당히 커집니다. +또한 개발 중에 코드 변경 사항이 동작하는지 확인하기 위해 컨테이너 이미지를 계속 빌드하게 되므로, 이렇게 절약되는 시간은 누중되어 상당히 커집니다. 그 다음 `Dockerfile`의 끝부분 근처에서 모든 코드를 복사합니다. 이 부분은 **가장 자주 변경되는** 부분이므로, 거의 항상 이 단계 이후에는 캐시를 사용할 수 없기 때문에 끝부분에 둡니다. @@ -352,7 +352,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage ## 확인하기 { #check-it } -Docker 컨테이너의 URL에서 확인할 수 있어야 합니다. 예를 들어: http://192.168.99.100/items/5?q=somequery 또는 http://127.0.0.1/items/5?q=somequery(또는 Docker 호스트를 사용해 동등하게 확인할 수 있습니다). +Docker 컨테이너의 URL에서 확인할 수 있어야 합니다. 예를 들어: [http://192.168.99.100/items/5?q=somequery](http://192.168.99.100/items/5?q=somequery) 또는 [http://127.0.0.1/items/5?q=somequery](http://127.0.0.1/items/5?q=somequery)(또는 Docker 호스트를 사용해 동등하게 확인할 수 있습니다). 아래와 같은 것을 보게 될 것입니다: @@ -362,17 +362,17 @@ Docker 컨테이너의 URL에서 확인할 수 있어야 합니다. 예를 들 ## 인터랙티브 API 문서 { #interactive-api-docs } -이제 http://192.168.99.100/docs 또는 http://127.0.0.1/docs(또는 Docker 호스트를 사용해 동등하게 접근)로 이동할 수 있습니다. +이제 [http://192.168.99.100/docs](http://192.168.99.100/docs) 또는 [http://127.0.0.1/docs](http://127.0.0.1/docs)(또는 Docker 호스트를 사용해 동등하게 접근)로 이동할 수 있습니다. -자동으로 생성된 인터랙티브 API 문서(Swagger UI 제공)를 볼 수 있습니다: +자동으로 생성된 인터랙티브 API 문서([Swagger UI](https://github.com/swagger-api/swagger-ui) 제공)를 볼 수 있습니다: ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) ## 대안 API 문서 { #alternative-api-docs } -또한 http://192.168.99.100/redoc 또는 http://127.0.0.1/redoc(또는 Docker 호스트를 사용해 동등하게 접근)로 이동할 수도 있습니다. +또한 [http://192.168.99.100/redoc](http://192.168.99.100/redoc) 또는 [http://127.0.0.1/redoc](http://127.0.0.1/redoc)(또는 Docker 호스트를 사용해 동등하게 접근)로 이동할 수도 있습니다. -대안 자동 문서(ReDoc 제공)를 볼 수 있습니다: +대안 자동 문서([ReDoc](https://github.com/Rebilly/ReDoc) 제공)를 볼 수 있습니다: ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -413,7 +413,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] ## 배포 개념 { #deployment-concepts } -컨테이너 관점에서 같은 [배포 개념](concepts.md){.internal-link target=_blank}들을 다시 이야기해 봅시다. +컨테이너 관점에서 같은 [배포 개념](concepts.md)들을 다시 이야기해 봅시다. 컨테이너는 주로 애플리케이션의 **빌드 및 배포** 과정을 단순화하는 도구이지만, 이러한 **배포 개념**을 처리하는 특정 접근 방식을 강제하지는 않으며, 가능한 전략은 여러 가지입니다. @@ -432,7 +432,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] FastAPI 애플리케이션의 **컨테이너 이미지**(그리고 나중에 실행 중인 **컨테이너**)에만 집중한다면, HTTPS는 보통 다른 도구에 의해 **외부적으로** 처리됩니다. -예를 들어 Traefik을 사용하는 다른 컨테이너가 **HTTPS**와 **인증서**의 **자동** 획득을 처리할 수 있습니다. +예를 들어 [Traefik](https://traefik.io/)을 사용하는 다른 컨테이너가 **HTTPS**와 **인증서**의 **자동** 획득을 처리할 수 있습니다. /// tip | 팁 @@ -558,7 +558,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] /// info | 정보 -Kubernetes를 사용한다면, 이는 아마도 Init Container일 것입니다. +Kubernetes를 사용한다면, 이는 아마도 [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)일 것입니다. /// @@ -570,7 +570,7 @@ Kubernetes를 사용한다면, 이는 아마도 tiangolo/uvicorn-gunicorn-fastapi. 하지만 이제는 deprecated되었습니다. ⛔️ +과거에는 공식 FastAPI Docker 이미지가 있었습니다: [tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker). 하지만 이제는 deprecated되었습니다. ⛔️ 아마도 이 베이스 도커 이미지(또는 유사한 다른 이미지)는 **사용하지 않는** 것이 좋습니다. @@ -600,7 +600,7 @@ Kubernetes를 사용한다면, 이는 아마도 uv를 사용한다면, uv Docker guide를 따를 수 있습니다. +프로젝트를 설치하고 관리하기 위해 [uv](https://github.com/astral-sh/uv)를 사용한다면, [uv Docker guide](https://docs.astral.sh/uv/guides/integration/docker/)를 따를 수 있습니다. ## 요약 { #recap } diff --git a/docs/ko/docs/deployment/fastapicloud.md b/docs/ko/docs/deployment/fastapicloud.md index 9a830b1579..a601f5416c 100644 --- a/docs/ko/docs/deployment/fastapicloud.md +++ b/docs/ko/docs/deployment/fastapicloud.md @@ -1,6 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -**한 번의 명령**으로 FastAPI 앱을 FastAPI Cloud에 배포할 수 있습니다. 아직이라면 대기자 명단에 등록해 보세요. 🚀 +**한 번의 명령**으로 FastAPI 앱을 [FastAPI Cloud](https://fastapicloud.com)에 배포할 수 있습니다. 아직이라면 대기자 명단에 등록해 보세요. 🚀 ## 로그인하기 { #login } @@ -40,7 +40,7 @@ Deploying to FastAPI Cloud... ## FastAPI Cloud 소개 { #about-fastapi-cloud } -**FastAPI Cloud**는 **FastAPI**를 만든 동일한 저자와 팀이 구축했습니다. +**[FastAPI Cloud](https://fastapicloud.com)**는 **FastAPI**를 만든 동일한 저자와 팀이 구축했습니다. 최소한의 노력으로 API를 **구축**, **배포**, **접근**하는 과정을 간소화합니다. diff --git a/docs/ko/docs/deployment/https.md b/docs/ko/docs/deployment/https.md index bda942af68..06ac147cdc 100644 --- a/docs/ko/docs/deployment/https.md +++ b/docs/ko/docs/deployment/https.md @@ -10,7 +10,7 @@ HTTPS는 그냥 “켜져 있거나” 아니면 “꺼져 있는” 것이라 /// -소비자 관점에서 **HTTPS의 기본을 배우려면** https://howhttps.works/를 확인하세요. +소비자 관점에서 **HTTPS의 기본을 배우려면** [https://howhttps.works/](https://howhttps.works/)를 확인하세요. 이제 **개발자 관점**에서 HTTPS를 생각할 때 염두에 두어야 할 여러 가지가 있습니다: @@ -28,13 +28,13 @@ HTTPS는 그냥 “켜져 있거나” 아니면 “꺼져 있는” 것이라 * **기본적으로** 이는 IP 주소 하나당 **HTTPS 인증서 하나만** 둘 수 있다는 뜻입니다. * 서버가 아무리 크든, 그 위에 올린 각 애플리케이션이 아무리 작든 상관없습니다. * 하지만 이에 대한 **해결책**이 있습니다. -* **TLS** 프로토콜(HTTP 이전, TCP 레벨에서 암호화를 처리하는 것)에 대한 **확장** 중에 **SNI**라는 것이 있습니다. +* **TLS** 프로토콜(HTTP 이전, TCP 레벨에서 암호화를 처리하는 것)에 대한 **확장** 중에 **[SNI](https://en.wikipedia.org/wiki/Server_Name_Indication)**라는 것이 있습니다. * 이 SNI 확장을 사용하면, 단일 서버(**단일 IP 주소**)에서 **여러 HTTPS 인증서**를 사용하고 **여러 HTTPS 도메인/애플리케이션**을 제공할 수 있습니다. * 이를 위해서는 서버에서 **공개 IP 주소**로 리스닝하는 **하나의** 컴포넌트(프로그램)가 서버에 있는 **모든 HTTPS 인증서**에 접근할 수 있어야 합니다. * 보안 연결을 얻은 **이후에도**, 통신 프로토콜 자체는 **여전히 HTTP**입니다. * **HTTP 프로토콜**로 전송되더라도, 내용은 **암호화**되어 있습니다. -일반적으로 서버(머신, 호스트 등)에는 **프로그램/HTTP 서버 하나**를 실행해 **HTTPS 관련 부분 전체**를 관리하게 합니다: **암호화된 HTTPS 요청**을 받고, 복호화된 **HTTP 요청**을 같은 서버에서 실행 중인 실제 HTTP 애플리케이션(이 경우 **FastAPI** 애플리케이션)으로 전달하고, 애플리케이션의 **HTTP 응답**을 받아 적절한 **HTTPS 인증서**로 **암호화**한 뒤 **HTTPS**로 클라이언트에 다시 보내는 역할입니다. 이런 서버를 흔히 **TLS Termination Proxy**라고 부릅니다. +일반적으로 서버(머신, 호스트 등)에는 **프로그램/HTTP 서버 하나**를 실행해 **HTTPS 관련 부분 전체**를 관리하게 합니다: **암호화된 HTTPS 요청**을 받고, 복호화된 **HTTP 요청**을 같은 서버에서 실행 중인 실제 HTTP 애플리케이션(이 경우 **FastAPI** 애플리케이션)으로 전달하고, 애플리케이션의 **HTTP 응답**을 받아 적절한 **HTTPS 인증서**로 **암호화**한 뒤 **HTTPS**로 클라이언트에 다시 보내는 역할입니다. 이런 서버를 흔히 **[TLS Termination Proxy](https://en.wikipedia.org/wiki/TLS_termination_proxy)**라고 부릅니다. TLS Termination Proxy로 사용할 수 있는 옵션은 다음과 같습니다: @@ -49,7 +49,7 @@ Let's Encrypt 이전에는 이러한 **HTTPS 인증서**가 신뢰할 수 있는 인증서를 획득하는 과정은 번거롭고, 꽤 많은 서류 작업이 필요했으며, 인증서도 상당히 비쌌습니다. -하지만 그 후 **Let's Encrypt**가 만들어졌습니다. +하지만 그 후 **[Let's Encrypt](https://letsencrypt.org/)**가 만들어졌습니다. 이는 Linux Foundation의 프로젝트입니다. 표준 암호학적 보안을 모두 사용하는 **HTTPS 인증서**를 **무료로**, 자동화된 방식으로 제공합니다. 이 인증서들은 수명이 짧고(약 3개월) 그래서 유효 기간이 짧은 만큼 **실제로 보안이 더 좋아지기도** 합니다. @@ -200,9 +200,9 @@ TLS Termination Proxy는 합의된 암호화를 사용해 **요청을 복호화* 프록시 헤더는 다음과 같습니다: -* X-Forwarded-For -* X-Forwarded-Proto -* X-Forwarded-Host +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) /// @@ -218,7 +218,7 @@ TLS Termination Proxy는 합의된 암호화를 사용해 **요청을 복호화* /// tip | 팁 -이에 대해서는 [프록시 뒤에서 실행하기 - 프록시 전달 헤더 활성화](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} 문서에서 더 알아볼 수 있습니다. +이에 대해서는 [프록시 뒤에서 실행하기 - 프록시 전달 헤더 활성화](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) 문서에서 더 알아볼 수 있습니다. /// diff --git a/docs/ko/docs/deployment/index.md b/docs/ko/docs/deployment/index.md index e0d2375344..74b3e0c718 100644 --- a/docs/ko/docs/deployment/index.md +++ b/docs/ko/docs/deployment/index.md @@ -16,7 +16,7 @@ 여러 도구를 조합해 직접 **서버를 배포**할 수도 있고, 작업의 일부를 대신해 주는 **클라우드 서비스**를 사용할 수도 있으며, 다른 가능한 선택지도 있습니다. -예를 들어, FastAPI 뒤에 있는 저희 팀은 FastAPI로 작업하는 것과 같은 개발자 경험을 유지하면서, FastAPI 앱을 클라우드에 가능한 한 간소화된 방식으로 배포할 수 있도록 **FastAPI Cloud**를 만들었습니다. +예를 들어, FastAPI 뒤에 있는 저희 팀은 FastAPI로 작업하는 것과 같은 개발자 경험을 유지하면서, FastAPI 앱을 클라우드에 가능한 한 간소화된 방식으로 배포할 수 있도록 [**FastAPI Cloud**](https://fastapicloud.com)를 만들었습니다. **FastAPI** 애플리케이션을 배포할 때 아마 염두에 두어야 할 몇 가지 주요 개념을 보여드리겠습니다(대부분은 다른 유형의 웹 애플리케이션에도 적용됩니다). diff --git a/docs/ko/docs/deployment/manually.md b/docs/ko/docs/deployment/manually.md index 93b1e76115..7199686829 100644 --- a/docs/ko/docs/deployment/manually.md +++ b/docs/ko/docs/deployment/manually.md @@ -52,11 +52,11 @@ FastAPI는 Uvicorn: 고성능 ASGI 서버. -* Hypercorn: HTTP/2 및 Trio 등 여러 기능과 호환되는 ASGI 서버. -* Daphne: Django Channels를 위해 만들어진 ASGI 서버. -* Granian: Python 애플리케이션을 위한 Rust HTTP 서버. -* NGINX Unit: NGINX Unit은 가볍고 다용도로 사용할 수 있는 웹 애플리케이션 런타임입니다. +* [Uvicorn](https://www.uvicorn.dev/): 고성능 ASGI 서버. +* [Hypercorn](https://hypercorn.readthedocs.io/): HTTP/2 및 Trio 등 여러 기능과 호환되는 ASGI 서버. +* [Daphne](https://github.com/django/daphne): Django Channels를 위해 만들어진 ASGI 서버. +* [Granian](https://github.com/emmett-framework/granian): Python 애플리케이션을 위한 Rust HTTP 서버. +* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): NGINX Unit은 가볍고 다용도로 사용할 수 있는 웹 애플리케이션 런타임입니다. ## 서버 머신과 서버 프로그램 { #server-machine-and-server-program } @@ -74,7 +74,7 @@ FastAPI를 설치하면 프로덕션 서버인 Uvicorn이 함께 설치되며, ` 하지만 ASGI 서버를 수동으로 설치할 수도 있습니다. -[가상 환경](../virtual-environments.md){.internal-link target=_blank}을 만들고 활성화한 다음, 서버 애플리케이션을 설치하세요. +[가상 환경](../virtual-environments.md)을 만들고 활성화한 다음, 서버 애플리케이션을 설치하세요. 예를 들어 Uvicorn을 설치하려면: @@ -94,7 +94,7 @@ $ pip install "uvicorn[standard]" `standard`를 추가하면 Uvicorn이 권장되는 추가 의존성 몇 가지를 설치하고 사용합니다. -여기에는 `asyncio`를 고성능으로 대체할 수 있는 드롭인 대체재인 `uvloop`가 포함되며, 큰 동시성 성능 향상을 제공합니다. +여기에는 `uvloop`가 포함되며, 이는 `asyncio`를 고성능으로 대체할 수 있는 드롭인 대체재로, 큰 동시성 성능 향상을 제공합니다. `pip install "fastapi[standard]"` 같은 방식으로 FastAPI를 설치하면 `uvicorn[standard]`도 함께 설치됩니다. diff --git a/docs/ko/docs/deployment/server-workers.md b/docs/ko/docs/deployment/server-workers.md index 1be102925e..9cc1a9a816 100644 --- a/docs/ko/docs/deployment/server-workers.md +++ b/docs/ko/docs/deployment/server-workers.md @@ -13,13 +13,13 @@ 애플리케이션을 배포할 때는 **다중 코어**를 활용하고 더 많은 요청을 처리할 수 있도록 **프로세스 복제**를 하고 싶을 가능성이 큽니다. -이전 장의 [배포 개념들](concepts.md){.internal-link target=_blank}에서 본 것처럼, 사용할 수 있는 전략이 여러 가지 있습니다. +이전 장의 [배포 개념들](concepts.md)에서 본 것처럼, 사용할 수 있는 전략이 여러 가지 있습니다. 여기서는 `fastapi` 명령어를 사용하거나 `uvicorn` 명령어를 직접 사용해서, **워커 프로세스**와 함께 **Uvicorn**을 사용하는 방법을 보여드리겠습니다. /// info | 정보 -Docker나 Kubernetes 같은 컨테이너를 사용하고 있다면, 다음 장인 [컨테이너에서의 FastAPI - 도커](docker.md){.internal-link target=_blank}에서 더 자세히 설명하겠습니다. +Docker나 Kubernetes 같은 컨테이너를 사용하고 있다면, 다음 장인 [컨테이너에서의 FastAPI - 도커](docker.md)에서 더 자세히 설명하겠습니다. 특히 **Kubernetes**에서 실행할 때는 워커를 사용하기보다는, 대신 **컨테이너당 단일 Uvicorn 프로세스 하나**를 실행하고 싶을 가능성이 크지만, 해당 내용은 그 장의 뒤에서 설명하겠습니다. @@ -126,7 +126,7 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 ## 컨테이너와 도커 { #containers-and-docker } -다음 장인 [컨테이너에서의 FastAPI - 도커](docker.md){.internal-link target=_blank}에서는 다른 **배포 개념들**을 처리하기 위해 사용할 수 있는 몇 가지 전략을 설명하겠습니다. +다음 장인 [컨테이너에서의 FastAPI - 도커](docker.md)에서는 다른 **배포 개념들**을 처리하기 위해 사용할 수 있는 몇 가지 전략을 설명하겠습니다. 단일 Uvicorn 프로세스를 실행하기 위해, **처음부터 여러분만의 이미지를 직접 빌드**하는 방법을 보여드리겠습니다. 이는 간단한 과정이며, **Kubernetes** 같은 분산 컨테이너 관리 시스템을 사용할 때 아마도 이렇게 하고 싶을 것입니다. diff --git a/docs/ko/docs/deployment/versions.md b/docs/ko/docs/deployment/versions.md index b94832aa82..fa1df45c30 100644 --- a/docs/ko/docs/deployment/versions.md +++ b/docs/ko/docs/deployment/versions.md @@ -4,7 +4,7 @@ 새로운 기능이 자주 추가되고, 버그가 규칙적으로 수정되며, 코드는 계속해서 지속적으로 개선되고 있습니다. -그래서 현재 버전이 아직 `0.x.x`인 것입니다. 이는 각 버전이 잠재적으로 하위 호환성이 깨지는 변경을 포함할 수 있음을 반영합니다. 이는 Semantic Versioning 관례를 따릅니다. +그래서 현재 버전이 아직 `0.x.x`인 것입니다. 이는 각 버전이 잠재적으로 하위 호환성이 깨지는 변경을 포함할 수 있음을 반영합니다. 이는 [Semantic Versioning](https://semver.org/) 관례를 따릅니다. 지금 바로 **FastAPI**로 프로덕션 애플리케이션을 만들 수 있습니다(그리고 아마도 한동안 그렇게 해오셨을 것입니다). 다만 나머지 코드와 함께 올바르게 동작하는 버전을 사용하고 있는지 확인하기만 하면 됩니다. @@ -34,7 +34,7 @@ fastapi[standard]>=0.112.0,<0.113.0 ## 이용 가능한 버전들 { #available-versions } -사용 가능한 버전(예: 현재 최신 버전이 무엇인지 확인하기 위해)은 [릴리스 노트](../release-notes.md){.internal-link target=_blank}에서 확인할 수 있습니다. +사용 가능한 버전(예: 현재 최신 버전이 무엇인지 확인하기 위해)은 [릴리스 노트](../release-notes.md)에서 확인할 수 있습니다. ## 버전들에 대해 { #about-versions } @@ -66,7 +66,7 @@ fastapi>=0.45.0,<0.46.0 앱에 테스트를 추가해야 합니다. -**FastAPI**에서는 매우 쉽습니다(Starlette 덕분에). 문서를 확인해 보세요: [테스트](../tutorial/testing.md){.internal-link target=_blank} +**FastAPI**에서는 매우 쉽습니다(Starlette 덕분에). 문서를 확인해 보세요: [테스트](../tutorial/testing.md) 테스트를 갖춘 뒤에는 **FastAPI** 버전을 더 최신 버전으로 업그레이드하고, 테스트를 실행하여 모든 코드가 올바르게 동작하는지 확인하세요. diff --git a/docs/ko/docs/environment-variables.md b/docs/ko/docs/environment-variables.md index e8809573fd..5b55960c8b 100644 --- a/docs/ko/docs/environment-variables.md +++ b/docs/ko/docs/environment-variables.md @@ -65,7 +65,7 @@ print(f"Hello {name} from Python") /// tip | 팁 -`os.getenv()` 의 두 번째 인자는 반환할 기본값입니다. +[`os.getenv()`](https://docs.python.org/3.8/library/os.html#os.getenv) 의 두 번째 인자는 반환할 기본값입니다. 제공하지 않으면 기본값은 `None`이며, 여기서는 사용할 기본값으로 `"World"`를 제공합니다. @@ -153,7 +153,7 @@ Hello World from Python /// tip | 팁 -The Twelve-Factor App: Config 에서 좀 더 자세히 알아볼 수 있습니다. +[The Twelve-Factor App: Config](https://12factor.net/config) 에서 좀 더 자세히 알아볼 수 있습니다. /// @@ -163,7 +163,7 @@ Hello World from Python 즉, 파이썬에서 환경 변수로부터 읽은 **모든 값**은 **`str`**이 되고, 다른 타입으로의 변환이나 검증은 코드에서 수행해야 합니다. -**애플리케이션 설정**을 처리하기 위한 환경 변수 사용에 대한 자세한 내용은 [고급 사용자 가이드 - 설정 및 환경 변수](./advanced/settings.md){.internal-link target=_blank} 에서 확인할 수 있습니다. +**애플리케이션 설정**을 처리하기 위한 환경 변수 사용에 대한 자세한 내용은 [고급 사용자 가이드 - 설정 및 환경 변수](./advanced/settings.md) 에서 확인할 수 있습니다. ## `PATH` 환경 변수 { #path-environment-variable } @@ -285,13 +285,13 @@ $ C:\opt\custompython\bin\python //// -이 정보는 [가상 환경](virtual-environments.md){.internal-link target=_blank} 에 대해 알아볼 때 유용할 것입니다. +이 정보는 [가상 환경](virtual-environments.md) 에 대해 알아볼 때 유용할 것입니다. ## 결론 { #conclusion } 이 문서를 통해 **환경 변수**가 무엇이고 파이썬에서 어떻게 사용하는지 기본적으로 이해하셨을 겁니다. -또한 환경 변수에 대한 위키피디아에서 이에 대해 자세히 알아볼 수 있습니다. +또한 [환경 변수에 대한 위키피디아](https://en.wikipedia.org/wiki/Environment_variable)에서 이에 대해 자세히 알아볼 수 있습니다. 많은 경우에서, 환경 변수가 어떻게 유용하고 적용 가능한지 바로 명확하게 알 수는 없습니다. 하지만 개발할 때 다양한 시나리오에서 계속 나타나므로 이에 대해 아는 것이 좋습니다. diff --git a/docs/ko/docs/fastapi-cli.md b/docs/ko/docs/fastapi-cli.md index 0d87ce3219..bfa16e8b38 100644 --- a/docs/ko/docs/fastapi-cli.md +++ b/docs/ko/docs/fastapi-cli.md @@ -1,15 +1,15 @@ # FastAPI CLI { #fastapi-cli } -**FastAPI CLI**는 FastAPI 애플리케이션을 서빙하고, FastAPI 프로젝트를 관리하는 등 다양한 작업에 사용할 수 있는 커맨드 라인 프로그램입니다. +**FastAPI CLI**는 FastAPI 애플리케이션을 서빙하고, FastAPI 프로젝트를 관리하는 등 다양한 작업에 사용할 수 있는 커맨드 라인 프로그램입니다. -FastAPI를 설치할 때(예: `pip install "fastapi[standard]"`), `fastapi-cli`라는 패키지가 포함되며, 이 패키지는 터미널에서 `fastapi` 명령어를 제공합니다. +FastAPI를 설치하면(예: `pip install "fastapi[standard]"`) 터미널에서 실행할 수 있는 커맨드 라인 프로그램이 함께 제공됩니다. 개발용으로 FastAPI 애플리케이션을 실행하려면 `fastapi dev` 명령어를 사용할 수 있습니다:
```console -$ fastapi dev main.py +$ fastapi dev FastAPI Starting development server 🚀 @@ -46,13 +46,66 @@ $ fastapi dev Uvicorn을 사용합니다. 😎 +또한 [VS Code 확장](editor-support.md)이나 [FastAPI Cloud](https://fastapicloud.com) 같은 다른 도구에서는 이를 찾지 못할 수도 있으므로, `pyproject.toml`의 `entrypoint`를 사용하는 것을 권장합니다. ## `fastapi dev` { #fastapi-dev } @@ -62,7 +115,7 @@ FastAPI CLI는 Python 프로그램의 경로(예: `main.py`)를 받아 `FastAPI` ## `fastapi run` { #fastapi-run } -`fastapi run`을 실행하면 기본적으로 프로덕션 모드로 FastAPI가 시작됩니다. +`fastapi run`을 실행하면 프로덕션 모드로 FastAPI가 시작됩니다. 기본적으로 **auto-reload**는 비활성화되어 있습니다. 또한 사용 가능한 모든 IP 주소를 의미하는 `0.0.0.0`에서 연결을 대기하므로, 해당 컴퓨터와 통신할 수 있는 누구에게나 공개적으로 접근 가능해집니다. 보통 프로덕션에서는 이렇게 실행하며, 예를 들어 컨테이너에서 이런 방식으로 실행합니다. @@ -70,6 +123,6 @@ FastAPI CLI는 Python 프로그램의 경로(예: `main.py`)를 받아 `FastAPI` /// tip | 팁 -자세한 내용은 [배포 문서](deployment/index.md){.internal-link target=_blank}에서 확인할 수 있습니다. +자세한 내용은 [배포 문서](deployment/index.md)에서 확인할 수 있습니다. /// diff --git a/docs/ko/docs/features.md b/docs/ko/docs/features.md index b511ae4707..0a5aa69436 100644 --- a/docs/ko/docs/features.md +++ b/docs/ko/docs/features.md @@ -6,8 +6,8 @@ ### 개방형 표준을 기반으로 { #based-on-open-standards } -* OpenAPI: 경로 처리, 매개변수, 요청 본문, 보안 등의 선언을 포함하여 API를 생성합니다. -* JSON Schema를 사용한 자동 데이터 모델 문서화(OpenAPI 자체가 JSON Schema를 기반으로 하기 때문입니다). +* [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification): 경로 처리, 매개변수, 요청 본문, 보안 등의 선언을 포함하여 API를 생성합니다. +* [**JSON Schema**](https://json-schema.org/)를 사용한 자동 데이터 모델 문서화(OpenAPI 자체가 JSON Schema를 기반으로 하기 때문입니다). * 단순히 떠올려서 덧붙인 레이어가 아니라, 세심한 검토를 거친 뒤 이러한 표준을 중심으로 설계되었습니다. * 이는 또한 다양한 언어로 자동 **클라이언트 코드 생성**을 사용할 수 있게 해줍니다. @@ -15,19 +15,19 @@ 대화형 API 문서와 탐색용 웹 사용자 인터페이스를 제공합니다. 프레임워크가 OpenAPI를 기반으로 하기에 여러 옵션이 있으며, 기본으로 2가지가 포함됩니다. -* 대화형 탐색이 가능한 Swagger UI로 브라우저에서 직접 API를 호출하고 테스트할 수 있습니다. +* [**Swagger UI**](https://github.com/swagger-api/swagger-ui)로 대화형 탐색이 가능하며 브라우저에서 직접 API를 호출하고 테스트할 수 있습니다. ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* ReDoc을 이용한 대체 API 문서화. +* [**ReDoc**](https://github.com/Rebilly/ReDoc)을 이용한 대체 API 문서화. ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) ### 그저 현대 파이썬 { #just-modern-python } -( Pydantic 덕분에) 모든 것이 표준 **Python 타입** 선언을 기반으로 합니다. 새로 배울 문법이 없습니다. 그저 표준적인 현대 파이썬입니다. +(Pydantic 덕분에) 모든 것이 표준 **Python 타입** 선언을 기반으로 합니다. 새로 배울 문법이 없습니다. 그저 표준적인 현대 파이썬입니다. -Python 타입을 어떻게 사용하는지 2분 정도 복습이 필요하다면(FastAPI를 사용하지 않더라도), 다음의 짧은 자습서를 확인하세요: [Python 타입](python-types.md){.internal-link target=_blank}. +Python 타입을 어떻게 사용하는지 2분 정도 복습이 필요하다면(FastAPI를 사용하지 않더라도), 다음의 짧은 자습서를 확인하세요: [Python 타입](python-types.md). 여러분은 타입이 있는 표준 Python을 다음과 같이 작성합니다: @@ -75,7 +75,7 @@ my_second_user: User = User(**second_user_data) 프레임워크 전체는 사용하기 쉽고 직관적으로 설계되었으며, 최고의 개발 경험을 보장하기 위해 개발을 시작하기도 전에 모든 결정은 여러 편집기에서 테스트되었습니다. -Python 개발자 설문조사에서 가장 많이 사용되는 기능 중 하나가 "자동 완성"이라는 점이 분명합니다. +Python 개발자 설문조사에서 [가장 많이 사용되는 기능 중 하나가 "자동 완성"이라는 점](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features)이 분명합니다. **FastAPI** 프레임워크 전체는 이를 만족하기 위해 만들어졌습니다. 자동 완성은 어디서나 작동합니다. @@ -83,11 +83,11 @@ Python 개발자 설문조사에서 Visual Studio Code에서: +* [Visual Studio Code](https://code.visualstudio.com/)에서: ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -* PyCharm에서: +* [PyCharm](https://www.jetbrains.com/pycharm/)에서: ![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) @@ -124,7 +124,7 @@ Python 개발자 설문조사에서 Starlette와 완전히 호환되며(또한 이를 기반으로 합니다). 따라서 추가로 가지고 있는 Starlette 코드도 모두 동작합니다. +**FastAPI**는 [**Starlette**](https://www.starlette.dev/)와 완전히 호환되며(또한 이를 기반으로 합니다). 따라서 추가로 가지고 있는 Starlette 코드도 모두 동작합니다. `FastAPI`는 실제로 `Starlette`의 하위 클래스입니다. 그래서 Starlette을 이미 알고 있거나 사용하고 있다면, 대부분의 기능이 같은 방식으로 동작할 것입니다. **FastAPI**를 사용하면 **Starlette**의 모든 기능을 얻게 됩니다(FastAPI는 Starlette에 강력한 기능을 더한 것입니다): -* 정말 인상적인 성능. **NodeJS**와 **Go**에 버금가는, 사용 가능한 가장 빠른 Python 프레임워크 중 하나입니다. +* 정말 인상적인 성능. [**NodeJS**와 **Go**에 버금가는, 사용 가능한 가장 빠른 Python 프레임워크 중 하나입니다](https://github.com/encode/starlette#performance). * **WebSocket** 지원. * 프로세스 내 백그라운드 작업. * 시작 및 종료 이벤트. @@ -177,7 +177,7 @@ FastAPI는 사용하기 매우 쉽지만, 매우 강력한 **FastAPI**에 대해 트윗 하고 저와 다른 사람들에게 FastAPI가 마음에 드는 이유를 알려주세요. 🎉 +[**FastAPI**에 대해 트윗](https://x.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi) 하고 저와 다른 사람들에게 FastAPI가 마음에 드는 이유를 알려주세요. 🎉 **FastAPI**가 어떻게 사용되고 있는지, 어떤 점이 마음에 들었는지, 어떤 프로젝트/회사에서 사용하고 있는지 등에 대해 듣고 싶습니다. ## FastAPI에 투표하기 { #vote-for-fastapi } -* Slant에서 **FastAPI** 에 대해 투표하십시오. -* AlternativeTo에서 **FastAPI** 에 대해 투표하십시오. -* StackShare에서 **FastAPI**를 사용한다고 표시하세요. +* [Slant에서 **FastAPI** 에 대해 투표하십시오](https://www.slant.co/options/34241/~fastapi-review). +* [AlternativeTo에서 **FastAPI** 에 대해 투표하십시오](https://alternativeto.net/software/fastapi/about/). +* [StackShare에서 **FastAPI**를 사용한다고 표시하세요](https://stackshare.io/pypi-fastapi). ## GitHub에서 질문으로 다른 사람 돕기 { #help-others-with-questions-in-github } 다른 사람들의 질문에 도움을 줄 수 있습니다: -* GitHub Discussions -* GitHub Issues +* [GitHub Discussions](https://github.com/fastapi/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered) +* [GitHub Issues](https://github.com/fastapi/fastapi/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Aquestion+-label%3Aanswered+) 많은 경우, 여러분은 이미 그 질문에 대한 답을 알고 있을 수도 있습니다. 🤓 -만약 많은 사람들의 질문을 도와준다면, 공식적인 [FastAPI 전문가](fastapi-people.md#fastapi-experts){.internal-link target=_blank}가 될 것입니다. 🎉 +만약 많은 사람들의 질문을 도와준다면, 공식적인 [FastAPI 전문가](fastapi-people.md#fastapi-experts)가 될 것입니다. 🎉 가장 중요한 점은: 친절하려고 노력하는 것입니다. 사람들은 좌절감을 안고 오며, 많은 경우 최선의 방식으로 질문하지 않을 수도 있습니다. 하지만 최대한 친절하게 대하려고 노력하세요. 🤗 @@ -104,7 +104,7 @@ GitHub에서 FastAPI를 "watch"할 수 있습니다 (오른쪽 상단 "watch" 많은 경우, 코드의 일부만 복사해서 올리지만, 그것만으로는 **문제를 재현**하기에 충분하지 않습니다. -* 질문자에게 최소한의 재현 가능한 예제를 제공해달라고 요청할 수 있습니다. 이렇게 하면 코드를 **복사-붙여넣기**하여 로컬에서 실행하고, 질문자가 보고 있는 것과 동일한 오류나 동작을 확인하거나 사용 사례를 더 잘 이해할 수 있습니다. +* 질문자에게 [최소한의 재현 가능한 예제](https://stackoverflow.com/help/minimal-reproducible-example)를 제공해달라고 요청할 수 있습니다. 이렇게 하면 코드를 **복사-붙여넣기**하여 로컬에서 실행하고, 질문자가 보고 있는 것과 동일한 오류나 동작을 확인하거나 사용 사례를 더 잘 이해할 수 있습니다. * 너그러운 마음이 든다면, 문제 설명만을 기반으로 직접 **예제를 만들어**볼 수도 있습니다. 다만 이는 시간이 많이 걸릴 수 있으므로, 먼저 문제를 명확히 해달라고 요청하는 것이 더 나을 수 있다는 점을 기억하세요. @@ -125,7 +125,7 @@ GitHub에서 FastAPI를 "watch"할 수 있습니다 (오른쪽 상단 "watch" ## GitHub 저장소 보기 { #watch-the-github-repository } -GitHub에서 FastAPI를 "watch"할 수 있습니다 (오른쪽 상단 "watch" 버튼을 클릭): https://github.com/fastapi/fastapi. 👀 +GitHub에서 FastAPI를 "watch"할 수 있습니다 (오른쪽 상단 "watch" 버튼을 클릭): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi). 👀 "Releases only" 대신 "Watching"을 선택하면 누군가가 새 이슈나 질문을 만들 때 알림을 받게 됩니다. 또한 새 이슈, 디스커션, PR 등만 알림을 받도록 지정할 수도 있습니다. @@ -133,7 +133,7 @@ GitHub에서 FastAPI를 "watch"할 수 있습니다 (오른쪽 상단 "watch" ## 질문하기 { #ask-questions } -GitHub 저장소에서 새 질문을 생성할 수 있습니다. 예를 들면 다음과 같습니다: +GitHub 저장소에서 [새 질문을 생성](https://github.com/fastapi/fastapi/discussions/new?category=questions)할 수 있습니다. 예를 들면 다음과 같습니다: * **질문**을 하거나 **문제**에 대해 질문합니다. * 새로운 **기능**을 제안 합니다. @@ -196,12 +196,12 @@ Pull request를 리뷰할 때 고려해야 할 사항과 방법은 다음과 같 ## Pull Request 만들기 { #create-a-pull-request } -Pull Requests를 이용하여 소스 코드에 [기여](contributing.md){.internal-link target=_blank}할 수 있습니다. 예를 들면 다음과 같습니다: +Pull Requests를 이용하여 소스 코드에 [기여](contributing.md)할 수 있습니다. 예를 들면 다음과 같습니다: * 문서에서 발견한 오타를 수정할 때. -* FastAPI에 대한 글, 비디오, 팟캐스트를 작성했거나 발견했다면 이 파일을 편집하여 공유할 때. +* FastAPI에 대한 글, 비디오, 팟캐스트를 작성했거나 발견했다면 [이 파일을 편집](https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml)하여 공유할 때. * 해당 섹션의 시작 부분에 링크를 추가해야 합니다. -* 여러분의 언어로 [문서 번역에](contributing.md#translations){.internal-link target=_blank} 도움을 줄 때. +* 여러분의 언어로 [문서 번역에](contributing.md#translations) 도움을 줄 때. * 다른 사람이 작성한 번역을 검토하는 것도 도울 수 있습니다. * 새로운 문서 섹션을 제안할 때. * 기존 이슈/버그를 수정할 때. @@ -218,8 +218,8 @@ Pull Requests를 이용하여 소스 코드에 [기여](contributing.md){.intern 지금 할 수 있는 주요 작업은: -* [GitHub에서 질문으로 다른 사람 돕기](#help-others-with-questions-in-github){.internal-link target=_blank} (위의 섹션을 참조하세요). -* [Pull Request 리뷰하기](#review-pull-requests){.internal-link target=_blank} (위의 섹션을 참조하세요). +* [GitHub에서 질문으로 다른 사람 돕기](#help-others-with-questions-in-github) (위의 섹션을 참조하세요). +* [Pull Request 리뷰하기](#review-pull-requests) (위의 섹션을 참조하세요). 이 두 작업이 **가장 많은 시간을 소모**합니다. 이것이 FastAPI를 유지 관리하는 주요 작업입니다. @@ -227,11 +227,11 @@ Pull Requests를 이용하여 소스 코드에 [기여](contributing.md){.intern ## 채팅에 참여하기 { #join-the-chat } -👥 Discord 채팅 서버 👥 에 참여해서 FastAPI 커뮤니티의 다른 사람들과 어울리세요. +👥 [Discord 채팅 서버](https://discord.gg/VQjSZaeJmf) 👥 에 참여해서 FastAPI 커뮤니티의 다른 사람들과 어울리세요. /// tip | 팁 -질문은 GitHub Discussions에서 하세요. [FastAPI Experts](fastapi-people.md#fastapi-experts){.internal-link target=_blank}로부터 도움을 받을 가능성이 훨씬 높습니다. +질문은 [GitHub Discussions](https://github.com/fastapi/fastapi/discussions/new?category=questions)에서 하세요. [FastAPI Experts](fastapi-people.md#fastapi-experts)로부터 도움을 받을 가능성이 훨씬 높습니다. 채팅은 다른 일반적인 대화를 위해서만 사용하세요. @@ -243,13 +243,13 @@ Pull Requests를 이용하여 소스 코드에 [기여](contributing.md){.intern GitHub에서는 템플릿이 올바른 질문을 작성하도록 안내하여 더 쉽게 좋은 답변을 얻거나, 질문하기 전에 스스로 문제를 해결할 수도 있습니다. 그리고 GitHub에서는 시간이 조금 걸리더라도 제가 항상 모든 것에 답하도록 보장할 수 있습니다. 채팅 시스템에서는 제가 개인적으로 그렇게 할 수 없습니다. 😅 -채팅 시스템에서의 대화 또한 GitHub만큼 쉽게 검색할 수 없기 때문에, 질문과 답변이 대화 속에서 사라질 수 있습니다. 그리고 GitHub에 있는 것만 [FastAPI Expert](fastapi-people.md#fastapi-experts){.internal-link target=_blank}가 되는 것으로 인정되므로, GitHub에서 더 많은 관심을 받게 될 가능성이 큽니다. +채팅 시스템에서의 대화 또한 GitHub만큼 쉽게 검색할 수 없기 때문에, 질문과 답변이 대화 속에서 사라질 수 있습니다. 그리고 GitHub에 있는 것만 [FastAPI Expert](fastapi-people.md#fastapi-experts)가 되는 것으로 인정되므로, GitHub에서 더 많은 관심을 받게 될 가능성이 큽니다. 반면, 채팅 시스템에는 수천 명의 사용자가 있으므로, 거의 항상 대화 상대를 찾을 가능성이 높습니다. 😄 ## 개발자 스폰서 되기 { #sponsor-the-author } -여러분의 **제품/회사**가 **FastAPI**에 의존하거나 관련되어 있고, FastAPI 사용자를 대상으로 알리고 싶다면 GitHub sponsors를 통해 개발자(저)를 스폰서할 수 있습니다. 티어에 따라 문서에 배지 같은 추가 혜택을 받을 수도 있습니다. 🎁 +여러분의 **제품/회사**가 **FastAPI**에 의존하거나 관련되어 있고, FastAPI 사용자를 대상으로 알리고 싶다면 [GitHub sponsors](https://github.com/sponsors/tiangolo)를 통해 개발자(저)를 스폰서할 수 있습니다. 티어에 따라 문서에 배지 같은 추가 혜택을 받을 수도 있습니다. 🎁 --- diff --git a/docs/ko/docs/history-design-future.md b/docs/ko/docs/history-design-future.md index d972001215..524eea59a4 100644 --- a/docs/ko/docs/history-design-future.md +++ b/docs/ko/docs/history-design-future.md @@ -1,6 +1,6 @@ # 역사, 디자인 그리고 미래 { #history-design-and-future } -얼마 전, 한 **FastAPI** 사용자가 이렇게 물었습니다: +얼마 전, [한 **FastAPI** 사용자가 이렇게 물었습니다](https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920): > 이 프로젝트의 역사는 무엇인가요? 몇 주 만에 아무 데서도 갑자기 나타나 엄청나게 좋아진 것처럼 보이네요 [...] @@ -14,7 +14,7 @@ **FastAPI**의 역사는 상당 부분 그 이전에 있던 도구들의 역사입니다. -[대안](alternatives.md){.internal-link target=_blank} 섹션에서 언급된 것처럼: +[대안](alternatives.md) 섹션에서 언급된 것처럼:
@@ -44,7 +44,7 @@ 가장 인기 있는 Python 편집기들: PyCharm, VS Code, Jedi 기반 편집기에서 여러 아이디어를 테스트했습니다. -약 80%의 사용자를 포함하는 최근 Python Developer Survey에 따르면 그렇습니다. +약 80%의 사용자를 포함하는 최근 [Python Developer Survey](https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools)에 따르면 그렇습니다. 즉, **FastAPI**는 Python 개발자의 80%가 사용하는 편집기들로 특별히 테스트되었습니다. 그리고 대부분의 다른 편집기도 유사하게 동작하는 경향이 있으므로, 그 모든 이점은 사실상 모든 편집기에서 동작해야 합니다. @@ -54,15 +54,15 @@ ## 필요조건 { #requirements } -여러 대안을 테스트한 후, 장점 때문에 **Pydantic**을 사용하기로 결정했습니다. +여러 대안을 테스트한 후, 장점 때문에 [**Pydantic**](https://docs.pydantic.dev/)을 사용하기로 결정했습니다. 그 후, JSON Schema를 완전히 준수하도록 하고, 제약 조건 선언을 정의하는 다양한 방식을 지원하며, 여러 편집기에서의 테스트를 바탕으로 편집기 지원(타입 검사, 자동 완성)을 개선하기 위해 기여했습니다. -개발 과정에서, 또 다른 핵심 필요조건인 **Starlette**에도 기여했습니다. +개발 과정에서, 또 다른 핵심 필요조건인 [**Starlette**](https://www.starlette.dev/)에도 기여했습니다. ## 개발 { #development } -**FastAPI** 자체를 만들기 시작했을 때쯤에는, 대부분의 조각들이 이미 갖춰져 있었고, 디자인은 정의되어 있었으며, 필요조건과 도구는 준비되어 있었고, 표준과 명세에 대한 지식도 명확하고 최신 상태였습니다. +**FastAPI** 자체를 만들기 시작했을 때쯤에는, 대부분의 조각들이 이미 갖춰져 있었고, 디자인은 정의되어 있었며, 필요조건과 도구는 준비되어 있었고, 표준과 명세에 대한 지식도 명확하고 최신 상태였습니다. ## 미래 { #future } @@ -76,4 +76,4 @@ **FastAPI**의 미래는 밝습니다. -그리고 [여러분의 도움](help-fastapi.md){.internal-link target=_blank}은 큰 힘이 됩니다. +그리고 [여러분의 도움](help-fastapi.md)은 큰 힘이 됩니다. diff --git a/docs/ko/docs/how-to/authentication-error-status-code.md b/docs/ko/docs/how-to/authentication-error-status-code.md index e039c073e9..c82ed0de22 100644 --- a/docs/ko/docs/how-to/authentication-error-status-code.md +++ b/docs/ko/docs/how-to/authentication-error-status-code.md @@ -2,7 +2,7 @@ FastAPI 버전 `0.122.0` 이전에는, 통합 보안 유틸리티가 인증 실패 후 클라이언트에 오류를 반환할 때 HTTP 상태 코드 `403 Forbidden`을 사용했습니다. -FastAPI 버전 `0.122.0`부터는 더 적절한 HTTP 상태 코드 `401 Unauthorized`를 사용하며, HTTP 명세인 RFC 7235, RFC 9110를 따라 응답에 합리적인 `WWW-Authenticate` 헤더를 반환합니다. +FastAPI 버전 `0.122.0`부터는 더 적절한 HTTP 상태 코드 `401 Unauthorized`를 사용하며, HTTP 명세인 [RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-3.1), [RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized)를 따라 응답에 합리적인 `WWW-Authenticate` 헤더를 반환합니다. 하지만 어떤 이유로든 클라이언트가 이전 동작에 의존하고 있다면, 보안 클래스에서 `make_not_authenticated_error` 메서드를 오버라이드하여 이전 동작으로 되돌릴 수 있습니다. diff --git a/docs/ko/docs/how-to/conditional-openapi.md b/docs/ko/docs/how-to/conditional-openapi.md index 3a87bf010b..b1617b1e83 100644 --- a/docs/ko/docs/how-to/conditional-openapi.md +++ b/docs/ko/docs/how-to/conditional-openapi.md @@ -10,7 +10,7 @@ 코드에 보안 결함이 있다면, 그 결함은 여전히 존재할 것입니다. -문서를 숨기는 것은 API와 상호작용하는 방법을 이해하기 어렵게 만들며, 프로덕션에서 디버깅을 더 어렵게 만들 수 있습니다. 이는 단순히 Security through obscurity의 한 형태로 간주될 수 있습니다. +문서를 숨기는 것은 API와 상호작용하는 방법을 이해하기 어렵게 만들며, 프로덕션에서 디버깅을 더 어렵게 만들 수 있습니다. 이는 단순히 [은폐를 통한 보안](https://en.wikipedia.org/wiki/Security_through_obscurity)의 한 형태로 간주될 수 있습니다. API를 보호하고 싶다면, 예를 들어 다음과 같은 더 나은 방법들이 있습니다: diff --git a/docs/ko/docs/how-to/configure-swagger-ui.md b/docs/ko/docs/how-to/configure-swagger-ui.md index b518fd8f72..8322266f5b 100644 --- a/docs/ko/docs/how-to/configure-swagger-ui.md +++ b/docs/ko/docs/how-to/configure-swagger-ui.md @@ -1,6 +1,6 @@ # Swagger UI 구성 { #configure-swagger-ui } -추가적인 Swagger UI 매개변수를 구성할 수 있습니다. +추가적인 [Swagger UI 매개변수](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/)를 구성할 수 있습니다. 구성을 하려면, `FastAPI()` 앱 객체를 생성할 때 또는 `get_swagger_ui_html()` 함수에 `swagger_ui_parameters` 인수를 전달하십시오. @@ -50,7 +50,7 @@ FastAPI는 대부분의 사용 사례에 적합한 몇 가지 기본 구성 매 ## 기타 Swagger UI 매개변수 { #other-swagger-ui-parameters } -사용할 수 있는 다른 모든 구성 옵션을 확인하려면, Swagger UI 매개변수에 대한 공식 Swagger UI 매개변수 문서를 참조하십시오. +사용할 수 있는 다른 모든 구성 옵션을 확인하려면, 공식 [Swagger UI 매개변수 문서](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/)를 참조하십시오. ## JavaScript 전용 설정 { #javascript-only-settings } diff --git a/docs/ko/docs/how-to/custom-docs-ui-assets.md b/docs/ko/docs/how-to/custom-docs-ui-assets.md index 7eb4b3cfdb..265eaca047 100644 --- a/docs/ko/docs/how-to/custom-docs-ui-assets.md +++ b/docs/ko/docs/how-to/custom-docs-ui-assets.md @@ -54,7 +54,7 @@ Swagger UI가 이 과정을 백그라운드에서 처리해 주지만, 이를 ### 테스트하기 { #test-it } -이제 http://127.0.0.1:8000/docs에서 문서에 접속한 뒤 페이지를 새로고침하면, 새 CDN에서 에셋을 불러오는 것을 확인할 수 있습니다. +이제 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)에서 문서에 접속한 뒤 페이지를 새로고침하면, 새 CDN에서 에셋을 불러오는 것을 확인할 수 있습니다. ## 문서용 JavaScript와 CSS 자체 호스팅하기 { #self-hosting-javascript-and-css-for-docs } @@ -93,12 +93,12 @@ JavaScript와 CSS를 자체 호스팅하는 것은 예를 들어, 오프라인 **Swagger UI**는 다음 파일을 사용합니다: -* `swagger-ui-bundle.js` -* `swagger-ui.css` +* [`swagger-ui-bundle.js`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js) +* [`swagger-ui.css`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css) **ReDoc**은 다음 파일을 사용합니다: -* `redoc.standalone.js` +* [`redoc.standalone.js`](https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js) 이후 파일 구조는 다음과 같을 수 있습니다: @@ -122,7 +122,7 @@ JavaScript와 CSS를 자체 호스팅하는 것은 예를 들어, 오프라인 ### 정적 파일 테스트하기 { #test-the-static-files } -애플리케이션을 시작하고 http://127.0.0.1:8000/static/redoc.standalone.js로 이동하세요. +애플리케이션을 시작하고 [http://127.0.0.1:8000/static/redoc.standalone.js](http://127.0.0.1:8000/static/redoc.standalone.js)로 이동하세요. **ReDoc**용 매우 긴 JavaScript 파일이 보일 것입니다. @@ -180,6 +180,6 @@ Swagger UI가 이 과정을 백그라운드에서 처리해 주지만, 이를 ### 정적 파일 UI 테스트하기 { #test-static-files-ui } -이제 WiFi 연결을 끊고 http://127.0.0.1:8000/docs에서 문서에 접속한 뒤 페이지를 새로고침해 보세요. +이제 WiFi 연결을 끊고 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)에서 문서에 접속한 뒤 페이지를 새로고침해 보세요. 인터넷이 없어도 API 문서를 보고, API와 상호작용할 수 있을 것입니다. diff --git a/docs/ko/docs/how-to/custom-request-and-route.md b/docs/ko/docs/how-to/custom-request-and-route.md index 335193bb35..99138a7370 100644 --- a/docs/ko/docs/how-to/custom-request-and-route.md +++ b/docs/ko/docs/how-to/custom-request-and-route.md @@ -18,7 +18,7 @@ 사용 사례에는 다음이 포함됩니다: -* JSON이 아닌 요청 바디를 JSON으로 변환하기(예: `msgpack`). +* JSON이 아닌 요청 바디를 JSON으로 변환하기(예: [`msgpack`](https://msgpack.org/index.html)). * gzip으로 압축된 요청 바디 압축 해제하기. * 모든 요청 바디를 자동으로 로깅하기. @@ -32,7 +32,7 @@ /// tip | 팁 -이 예시는 동작 방식 시연을 위한 장난감 예제입니다. Gzip 지원이 필요하다면 제공되는 [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank}를 사용할 수 있습니다. +이 예시는 동작 방식 시연을 위한 장난감 예제입니다. Gzip 지원이 필요하다면 제공되는 [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware)를 사용할 수 있습니다. /// @@ -66,7 +66,7 @@ 그리고 이 두 가지, `scope`와 `receive`가 새로운 `Request` 인스턴스를 만드는 데 필요한 것들입니다. -`Request`에 대해 더 알아보려면 Starlette의 Requests 문서를 확인하세요. +`Request`에 대해 더 알아보려면 [Starlette의 Requests 문서](https://www.starlette.dev/requests/)를 확인하세요. /// @@ -82,7 +82,7 @@ /// tip | 팁 -같은 문제를 해결하려면 `RequestValidationError`에 대한 커스텀 핸들러에서 `body`를 사용하는 편이 아마 훨씬 더 쉽습니다([오류 처리하기](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}). +같은 문제를 해결하려면 `RequestValidationError`에 대한 커스텀 핸들러에서 `body`를 사용하는 편이 아마 훨씬 더 쉽습니다([오류 처리하기](../tutorial/handling-errors.md#use-the-requestvalidationerror-body)). 하지만 이 예시도 여전히 유효하며, 내부 컴포넌트와 상호작용하는 방법을 보여줍니다. diff --git a/docs/ko/docs/how-to/extending-openapi.md b/docs/ko/docs/how-to/extending-openapi.md index 0589e479bf..992243dbe5 100644 --- a/docs/ko/docs/how-to/extending-openapi.md +++ b/docs/ko/docs/how-to/extending-openapi.md @@ -37,7 +37,7 @@ 위 정보를 바탕으로, 동일한 유틸리티 함수를 사용해 OpenAPI 스키마를 생성하고 필요한 각 부분을 덮어쓸 수 있습니다. -예를 들어, 커스텀 로고를 포함하기 위한 ReDoc의 OpenAPI 확장을 추가해 보겠습니다. +예를 들어, [커스텀 로고를 포함하기 위한 ReDoc의 OpenAPI 확장](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo)을 추가해 보겠습니다. ### 일반적인 **FastAPI** { #normal-fastapi } @@ -75,6 +75,6 @@ ### 확인하기 { #check-it } -http://127.0.0.1:8000/redoc로 이동하면 커스텀 로고(이 예시에서는 **FastAPI** 로고)를 사용하는 것을 확인할 수 있습니다: +[http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)로 이동하면 커스텀 로고(이 예시에서는 **FastAPI** 로고)를 사용하는 것을 확인할 수 있습니다: diff --git a/docs/ko/docs/how-to/general.md b/docs/ko/docs/how-to/general.md index a18dc68a21..28f9535bc7 100644 --- a/docs/ko/docs/how-to/general.md +++ b/docs/ko/docs/how-to/general.md @@ -4,36 +4,40 @@ ## 데이터 필터링 - 보안 { #filter-data-security } -반환하면 안 되는 데이터를 과도하게 반환하지 않도록 하려면, [튜토리얼 - 응답 모델 - 반환 타입](../tutorial/response-model.md){.internal-link target=_blank} 문서를 읽어보세요. +반환하면 안 되는 데이터를 과도하게 반환하지 않도록 하려면, [튜토리얼 - 응답 모델 - 반환 타입](../tutorial/response-model.md) 문서를 읽어보세요. + +## 응답 성능 최적화 - 응답 모델 - 반환 타입 { #optimize-response-performance-response-model-return-type } + +JSON 데이터를 반환할 때 성능을 최적화하려면 반환 타입 또는 응답 모델을 사용하세요. 그러면 Pydantic이 Python을 거치지 않고 Rust 측에서 JSON 직렬화를 처리합니다. 자세한 내용은 [튜토리얼 - 응답 모델 - 반환 타입](../tutorial/response-model.md) 문서를 참고하세요. ## 문서화 태그 - OpenAPI { #documentation-tags-openapi } -*경로 처리*에 태그를 추가하고, 문서 UI에서 이를 그룹화하려면 [튜토리얼 - 경로 처리 구성 - 태그](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank} 문서를 읽어보세요. +*경로 처리*에 태그를 추가하고, 문서 UI에서 이를 그룹화하려면 [튜토리얼 - 경로 처리 구성 - 태그](../tutorial/path-operation-configuration.md#tags) 문서를 읽어보세요. ## 문서화 요약 및 설명 - OpenAPI { #documentation-summary-and-description-openapi } -*경로 처리*에 요약과 설명을 추가하고, 문서 UI에 표시하려면 [튜토리얼 - 경로 처리 구성 - 요약 및 설명](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank} 문서를 읽어보세요. +*경로 처리*에 요약과 설명을 추가하고, 문서 UI에 표시하려면 [튜토리얼 - 경로 처리 구성 - 요약 및 설명](../tutorial/path-operation-configuration.md#summary-and-description) 문서를 읽어보세요. ## 문서화 응답 설명 - OpenAPI { #documentation-response-description-openapi } -문서 UI에 표시되는 응답의 설명을 정의하려면 [튜토리얼 - 경로 처리 구성 - 응답 설명](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank} 문서를 읽어보세요. +문서 UI에 표시되는 응답의 설명을 정의하려면 [튜토리얼 - 경로 처리 구성 - 응답 설명](../tutorial/path-operation-configuration.md#response-description) 문서를 읽어보세요. ## 문서화 *경로 처리* 지원 중단하기 - OpenAPI { #documentation-deprecate-a-path-operation-openapi } -*경로 처리*를 지원 중단(deprecate)으로 표시하고, 문서 UI에 보여주려면 [튜토리얼 - 경로 처리 구성 - 지원 중단](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank} 문서를 읽어보세요. +*경로 처리*를 지원 중단(deprecate)으로 표시하고, 문서 UI에 보여주려면 [튜토리얼 - 경로 처리 구성 - 지원 중단](../tutorial/path-operation-configuration.md#deprecate-a-path-operation) 문서를 읽어보세요. ## 어떤 데이터든 JSON 호환으로 변환하기 { #convert-any-data-to-json-compatible } -어떤 데이터든 JSON 호환 형식으로 변환하려면 [튜토리얼 - JSON 호환 인코더](../tutorial/encoder.md){.internal-link target=_blank} 문서를 읽어보세요. +어떤 데이터든 JSON 호환 형식으로 변환하려면 [튜토리얼 - JSON 호환 인코더](../tutorial/encoder.md) 문서를 읽어보세요. ## OpenAPI 메타데이터 - 문서 { #openapi-metadata-docs } -라이선스, 버전, 연락처 등의 정보를 포함해 OpenAPI 스키마에 메타데이터를 추가하려면 [튜토리얼 - 메타데이터와 문서 URL](../tutorial/metadata.md){.internal-link target=_blank} 문서를 읽어보세요. +라이선스, 버전, 연락처 등의 정보를 포함해 OpenAPI 스키마에 메타데이터를 추가하려면 [튜토리얼 - 메타데이터와 문서 URL](../tutorial/metadata.md) 문서를 읽어보세요. ## OpenAPI 사용자 정의 URL { #openapi-custom-url } -OpenAPI URL을 커스터마이즈(또는 제거)하려면 [튜토리얼 - 메타데이터와 문서 URL](../tutorial/metadata.md#openapi-url){.internal-link target=_blank} 문서를 읽어보세요. +OpenAPI URL을 커스터마이즈(또는 제거)하려면 [튜토리얼 - 메타데이터와 문서 URL](../tutorial/metadata.md#openapi-url) 문서를 읽어보세요. ## OpenAPI 문서 URL { #openapi-docs-urls } -자동으로 생성되는 문서 사용자 인터페이스에서 사용하는 URL을 업데이트하려면 [튜토리얼 - 메타데이터와 문서 URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank} 문서를 읽어보세요. +자동으로 생성되는 문서 사용자 인터페이스에서 사용하는 URL을 업데이트하려면 [튜토리얼 - 메타데이터와 문서 URL](../tutorial/metadata.md#docs-urls) 문서를 읽어보세요. diff --git a/docs/ko/docs/how-to/graphql.md b/docs/ko/docs/how-to/graphql.md index a960e6d8b2..c4353d57d3 100644 --- a/docs/ko/docs/how-to/graphql.md +++ b/docs/ko/docs/how-to/graphql.md @@ -18,18 +18,18 @@ 다음은 **ASGI** 지원이 있는 **GraphQL** 라이브러리들입니다. **FastAPI**와 함께 사용할 수 있습니다: -* Strawberry 🍓 - * FastAPI용 문서 제공 -* Ariadne - * FastAPI용 문서 제공 -* Tartiflette - * ASGI 통합을 제공하기 위해 Tartiflette ASGI 사용 -* Graphene - * starlette-graphene3 사용 +* [Strawberry](https://strawberry.rocks/) 🍓 + * [FastAPI용 문서](https://strawberry.rocks/docs/integrations/fastapi) 제공 +* [Ariadne](https://ariadnegraphql.org/) + * [FastAPI용 문서](https://ariadnegraphql.org/docs/fastapi-integration) 제공 +* [Tartiflette](https://tartiflette.io/) + * ASGI 통합을 제공하기 위해 [Tartiflette ASGI](https://tartiflette.github.io/tartiflette-asgi/) 사용 +* [Graphene](https://graphene-python.org/) + * [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3) 사용 ## Strawberry로 GraphQL 사용하기 { #graphql-with-strawberry } -**GraphQL**로 작업해야 하거나 작업하고 싶다면, **Strawberry**를 **권장**합니다. **FastAPI**의 설계와 가장 가깝고, 모든 것이 **type annotations**에 기반해 있기 때문입니다. +**GraphQL**로 작업해야 하거나 작업하고 싶다면, [**Strawberry**](https://strawberry.rocks/)를 **권장**합니다. **FastAPI**의 설계와 가장 가깝고, 모든 것이 **type annotations**에 기반해 있기 때문입니다. 사용 사례에 따라 다른 라이브러리를 선호할 수도 있지만, 제게 묻는다면 아마 **Strawberry**를 먼저 시도해 보라고 제안할 것입니다. @@ -37,24 +37,24 @@ {* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} -Strawberry 문서에서 Strawberry에 대해 더 알아볼 수 있습니다. +[Strawberry 문서](https://strawberry.rocks/)에서 Strawberry에 대해 더 알아볼 수 있습니다. -또한 FastAPI에서 Strawberry 사용에 대한 문서도 확인해 보세요. +또한 [FastAPI에서 Strawberry 사용](https://strawberry.rocks/docs/integrations/fastapi)에 대한 문서도 확인해 보세요. ## Starlette의 예전 `GraphQLApp` { #older-graphqlapp-from-starlette } -이전 버전의 Starlette에는 Graphene과 통합하기 위한 `GraphQLApp` 클래스가 포함되어 있었습니다. +이전 버전의 Starlette에는 [Graphene](https://graphene-python.org/)과 통합하기 위한 `GraphQLApp` 클래스가 포함되어 있었습니다. -이것은 Starlette에서 deprecated 되었지만, 이를 사용하던 코드가 있다면 같은 사용 사례를 다루고 **거의 동일한 인터페이스**를 가진 starlette-graphene3로 쉽게 **마이그레이션**할 수 있습니다. +이것은 Starlette에서 deprecated 되었지만, 이를 사용하던 코드가 있다면 같은 사용 사례를 다루고 **거의 동일한 인터페이스**를 가진 [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3)로 쉽게 **마이그레이션**할 수 있습니다. /// tip | 팁 -GraphQL이 필요하다면, 커스텀 클래스와 타입 대신 type annotations에 기반한 Strawberry를 여전히 확인해 보시길 권장합니다. +GraphQL이 필요하다면, 커스텀 클래스와 타입 대신 type annotations에 기반한 [Strawberry](https://strawberry.rocks/)를 여전히 확인해 보시길 권장합니다. /// ## 더 알아보기 { #learn-more } -공식 GraphQL 문서에서 **GraphQL**에 대해 더 알아볼 수 있습니다. +[공식 GraphQL 문서](https://graphql.org/)에서 **GraphQL**에 대해 더 알아볼 수 있습니다. 또한 위에서 설명한 각 라이브러리에 대해서도 해당 링크에서 더 자세히 읽어볼 수 있습니다. diff --git a/docs/ko/docs/how-to/index.md b/docs/ko/docs/how-to/index.md index 9321c488bd..f80f9f3586 100644 --- a/docs/ko/docs/how-to/index.md +++ b/docs/ko/docs/how-to/index.md @@ -8,6 +8,6 @@ /// tip | 팁 -**FastAPI를 구조적으로 학습**하고 싶다면(권장), 대신 [튜토리얼 - 사용자 가이드](../tutorial/index.md){.internal-link target=_blank}를 장별로 읽어보세요. +**FastAPI를 구조적으로 학습**하고 싶다면(권장), 대신 [튜토리얼 - 사용자 가이드](../tutorial/index.md)를 장별로 읽어보세요. /// diff --git a/docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 5dd40cbdc2..d47f0bc415 100644 --- a/docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -10,7 +10,7 @@ FastAPI 0.126.0 버전에서는 Pydantic v1 지원을 중단했지만, `pydantic /// warning | 경고 -Pydantic 팀은 **Python 3.14**부터 최신 Python 버전에서 Pydantic v1 지원을 중단했습니다. +Pydantic 팀은 최신 Python 버전에서 Pydantic v1 지원을 중단했으며, 시작 버전은 **Python 3.14**입니다. 여기에는 `pydantic.v1`도 포함되며, Python 3.14 이상에서는 더 이상 지원되지 않습니다. @@ -22,7 +22,7 @@ Pydantic v1을 사용하는 오래된 FastAPI 앱이 있다면, 여기서는 이 ## 공식 가이드 { #official-guide } -Pydantic에는 v1에서 v2로의 공식 마이그레이션 가이드가 있습니다. +Pydantic에는 v1에서 v2로의 공식 [마이그레이션 가이드](https://docs.pydantic.dev/latest/migration/)가 있습니다. 여기에는 무엇이 바뀌었는지, 검증이 이제 어떻게 더 정확하고 엄격해졌는지, 가능한 주의사항 등도 포함되어 있습니다. @@ -30,7 +30,7 @@ Pydantic에는 v1에서 v2로의 공식 `bump-pydantic`를 사용할 수 있습니다. +같은 Pydantic 팀이 제공하는 [`bump-pydantic`](https://github.com/pydantic/bump-pydantic)를 사용할 수 있습니다. 이 도구는 변경해야 하는 코드의 대부분을 자동으로 바꾸는 데 도움을 줍니다. diff --git a/docs/ko/docs/how-to/testing-database.md b/docs/ko/docs/how-to/testing-database.md index 2d7798d707..fe0bec809c 100644 --- a/docs/ko/docs/how-to/testing-database.md +++ b/docs/ko/docs/how-to/testing-database.md @@ -1,7 +1,7 @@ # 데이터베이스 테스트하기 { #testing-a-database } -데이터베이스, SQL, SQLModel에 대해서는 SQLModel 문서에서 학습할 수 있습니다. 🤓 +데이터베이스, SQL, SQLModel에 대해서는 [SQLModel 문서](https://sqlmodel.tiangolo.com/)에서 학습할 수 있습니다. 🤓 -FastAPI에서 SQLModel을 사용하는 방법에 대한 미니 튜토리얼도 있습니다. ✨ +[FastAPI에서 SQLModel을 사용하는 방법에 대한 미니 튜토리얼](https://sqlmodel.tiangolo.com/tutorial/fastapi/)도 있습니다. ✨ -해당 튜토리얼에는 SQL 데이터베이스 테스트에 대한 섹션도 포함되어 있습니다. 😎 +해당 튜토리얼에는 [SQL 데이터베이스 테스트](https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/)에 대한 섹션도 포함되어 있습니다. 😎 diff --git a/docs/ko/docs/index.md b/docs/ko/docs/index.md index d2e08be16f..91d27fcee9 100644 --- a/docs/ko/docs/index.md +++ b/docs/ko/docs/index.md @@ -11,25 +11,25 @@ FastAPI 프레임워크, 고성능, 간편한 학습, 빠른 코드 작성, 준비된 프로덕션

- + Test - + Coverage - + Package version - + Supported Python versions

--- -**문서**: https://fastapi.tiangolo.com +**문서**: [https://fastapi.tiangolo.com/ko](https://fastapi.tiangolo.com/ko) -**소스 코드**: https://github.com/fastapi/fastapi +**소스 코드**: [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi) --- @@ -44,7 +44,7 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트 * **쉬움**: 쉽게 사용하고 배우도록 설계. 적은 문서 읽기 시간. * **짧음**: 코드 중복 최소화. 각 매개변수 선언의 여러 기능. 적은 버그. * **견고함**: 준비된 프로덕션 용 코드를 얻으십시오. 자동 대화형 문서와 함께. -* **표준 기반**: API에 대한 (완전히 호환되는) 개방형 표준 기반: OpenAPI (이전에 Swagger로 알려졌던) 및 JSON Schema. +* **표준 기반**: API에 대한 (완전히 호환되는) 개방형 표준 기반: [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (이전에 Swagger로 알려졌던) 및 [JSON Schema](https://json-schema.org/). * 내부 개발팀의 프로덕션 애플리케이션을 빌드한 테스트에 근거한 측정 @@ -55,51 +55,51 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트 ### 키스톤 스폰서 { #keystone-sponsor } {% for sponsor in sponsors.keystone -%} - + {% endfor -%} ### 골드 및 실버 스폰서 { #gold-and-silver-sponsors } {% for sponsor in sponsors.gold -%} - + {% endfor -%} {%- for sponsor in sponsors.silver -%} - + {% endfor %} -다른 스폰서 +[다른 스폰서](https://fastapi.tiangolo.com/ko/fastapi-people/#sponsors) ## 의견들 { #opinions } "_[...] 저는 요즘 **FastAPI**를 많이 사용하고 있습니다. [...] 사실 우리 팀의 **마이크로소프트 ML 서비스** 전부를 바꿀 계획입니다. 그중 일부는 핵심 **Windows**와 몇몇의 **Office** 제품들이 통합되고 있습니다._" -
Kabir Khan - 마이크로소프트 (ref)
+
Kabir Khan - 마이크로소프트 (ref)
--- "_**FastAPI** 라이브러리를 채택하여 **예측**을 얻기 위해 쿼리를 실행 할 수 있는 **REST** 서버를 생성했습니다. [Ludwig을 위해]_" -
Piero Molino, Yaroslav Dudin 그리고 Sai Sumanth Miryala - 우버 (ref)
+
Piero Molino, Yaroslav Dudin 그리고 Sai Sumanth Miryala - 우버 (ref)
--- "_**Netflix**는 우리의 오픈 소스 배포판인 **위기 관리** 오케스트레이션 프레임워크를 발표할 수 있어 기쁩니다: 바로 **Dispatch**입니다! [**FastAPI**로 빌드]_" -
Kevin Glisson, Marc Vilanova, Forest Monsen - 넷플릭스 (ref)
+
Kevin Glisson, Marc Vilanova, Forest Monsen - 넷플릭스 (ref)
--- "_**FastAPI**가 너무 좋아서 구름 위를 걷는듯 합니다. 정말 즐겁습니다!_" -
Brian Okken - Python Bytes 팟캐스트 호스트 (ref)
+
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) podcast host (ref)
--- "_솔직히, 당신이 만든 것은 매우 견고하고 세련되어 보입니다. 여러 면에서 **Hug**가 이렇게 되었으면 합니다 - 그걸 만든 누군가를 보는 것은 많은 영감을 줍니다._" -
Timothy Crosley - Hug 제작자 (ref)
+
Timothy Crosley - [Hug](https://github.com/hugapi/hug) 제작자 (ref)
--- @@ -107,27 +107,27 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트 "_우리 **API**를 **FastAPI**로 바꿨습니다 [...] 아마 여러분도 좋아하실 것입니다 [...]_" -
Ines Montani - Matthew Honnibal - Explosion AI 설립자 - spaCy 제작자 (ref) - (ref)
+
Ines Montani - Matthew Honnibal - [Explosion AI](https://explosion.ai) 설립자 - [spaCy](https://spacy.io) 제작자 (ref) - (ref)
--- "_프로덕션 Python API를 만들고자 한다면, 저는 **FastAPI**를 강력히 추천합니다. **아름답게 설계**되었고, **사용이 간단**하며, **확장성이 매우 뛰어나**고, 우리의 API 우선 개발 전략에서 **핵심 구성 요소**가 되었으며 Virtual TAC Engineer 같은 많은 자동화와 서비스를 이끌고 있습니다._" -
Deon Pillsbury - Cisco (ref)
+
Deon Pillsbury - Cisco (ref)
--- ## FastAPI 미니 다큐멘터리 { #fastapi-mini-documentary } -2025년 말에 공개된 FastAPI 미니 다큐멘터리가 있습니다. 온라인에서 시청할 수 있습니다: +2025년 말에 공개된 [FastAPI 미니 다큐멘터리](https://www.youtube.com/watch?v=mpR8ngthqiE)가 있습니다. 온라인에서 시청할 수 있습니다: -FastAPI Mini Documentary +FastAPI Mini Documentary ## **Typer**, CLI를 위한 FastAPI { #typer-the-fastapi-of-clis } - + -웹 API 대신 터미널에서 사용할 CLI 앱을 만들고 있다면, **Typer**를 확인해 보십시오. +웹 API 대신 터미널에서 사용할 CLI 앱을 만들고 있다면, [**Typer**](https://typer.tiangolo.com/)를 확인해 보십시오. **Typer**는 FastAPI의 동생입니다. 그리고 **CLI를 위한 FastAPI**가 되기 위해 생겼습니다. ⌨️ 🚀 @@ -135,12 +135,12 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트 FastAPI는 거인들의 어깨 위에 서 있습니다: -* 웹 부분을 위한 Starlette. -* 데이터 부분을 위한 Pydantic. +* [Starlette](https://www.starlette.dev/) — 웹 부분을 담당합니다. +* [Pydantic](https://docs.pydantic.dev/) — 데이터 부분을 담당합니다. ## 설치 { #installation } -가상 환경을 생성하고 활성화한 다음 FastAPI를 설치하세요: +[가상 환경](https://fastapi.tiangolo.com/ko/virtual-environments/)을 생성하고 활성화한 다음 FastAPI를 설치하세요:
@@ -199,7 +199,7 @@ async def read_item(item_id: int, q: str | None = None): **Note**: -잘 모르겠다면, 문서에서 `async`와 `await`에 관한 _"급하세요?"_ 섹션을 확인해 보십시오. +잘 모르겠다면, ["급하세요?"](https://fastapi.tiangolo.com/ko/async/#in-a-hurry) 섹션을 확인해 보십시오. @@ -210,7 +210,7 @@ async def read_item(item_id: int, q: str | None = None):
```console -$ fastapi dev main.py +$ fastapi dev ╭────────── FastAPI CLI - Development mode ───────────╮ │ │ @@ -235,19 +235,19 @@ INFO: Application startup complete.
-fastapi dev main.py 명령에 관하여... +fastapi dev 명령에 관하여... -`fastapi dev` 명령은 `main.py` 파일을 읽고, 그 안의 **FastAPI** 앱을 감지한 다음, Uvicorn을 사용해 서버를 시작합니다. +`fastapi dev` 명령은 여러분의 `main.py` 파일을 자동으로 읽고, 그 안의 **FastAPI** 앱을 감지한 다음, [Uvicorn](https://www.uvicorn.dev)을 사용해 서버를 시작합니다. 기본적으로 `fastapi dev`는 로컬 개발을 위해 auto-reload가 활성화된 상태로 시작됩니다. -자세한 내용은 FastAPI CLI 문서에서 확인할 수 있습니다. +자세한 내용은 [FastAPI CLI 문서](https://fastapi.tiangolo.com/ko/fastapi-cli/)에서 확인할 수 있습니다.
### 확인하기 { #check-it } -브라우저로 http://127.0.0.1:8000/items/5?q=somequery를 열어보십시오. +브라우저로 [http://127.0.0.1:8000/items/5?q=somequery](http://127.0.0.1:8000/items/5?q=somequery)를 열어보십시오. 아래의 JSON 응답을 볼 수 있습니다: @@ -264,17 +264,17 @@ INFO: Application startup complete. ### 대화형 API 문서 { #interactive-api-docs } -이제 http://127.0.0.1:8000/docs로 가보십시오. +이제 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)로 가보십시오. -자동 대화형 API 문서를 볼 수 있습니다 (Swagger UI 제공): +자동 대화형 API 문서를 볼 수 있습니다 ([Swagger UI](https://github.com/swagger-api/swagger-ui) 제공): ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) ### 대안 API 문서 { #alternative-api-docs } -그리고 이제 http://127.0.0.1:8000/redoc로 가봅시다. +그리고 이제 [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)로 가봅시다. -다른 자동 문서를 볼 수 있습니다(ReDoc 제공): +다른 자동 문서를 볼 수 있습니다([ReDoc](https://github.com/Rebilly/ReDoc) 제공): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -316,7 +316,7 @@ def update_item(item_id: int, item: Item): ### 대화형 API 문서 업그레이드 { #interactive-api-docs-upgrade } -이제 http://127.0.0.1:8000/docs로 이동합니다. +이제 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)로 이동합니다. * 대화형 API 문서는 새 본문을 포함해 자동으로 업데이트됩니다: @@ -332,7 +332,7 @@ def update_item(item_id: int, item: Item): ### 대안 API 문서 업그레이드 { #alternative-api-docs-upgrade } -그리고 이제, http://127.0.0.1:8000/redoc로 이동합니다. +그리고 이제, [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)로 이동합니다. * 대안 문서 역시 새 쿼리 매개변수와 본문을 반영합니다: @@ -442,7 +442,7 @@ item: Item * 강력하고 사용하기 쉬운 **의존성 주입** 시스템. * **OAuth2** 지원을 포함한 **JWT tokens** 및 **HTTP Basic**을 갖는 보안과 인증. * (Pydantic 덕분에) **깊은 중첩 JSON 모델**을 선언하는데 더 진보한 (하지만 마찬가지로 쉬운) 기술. -* Strawberry 및 기타 라이브러리와의 **GraphQL** 통합. +* [Strawberry](https://strawberry.rocks) 및 기타 라이브러리와의 **GraphQL** 통합. * (Starlette 덕분에) 많은 추가 기능: * **웹 소켓** * HTTPX 및 `pytest`에 기반한 극히 쉬운 테스트 @@ -452,24 +452,10 @@ item: Item ### 앱 배포하기(선택 사항) { #deploy-your-app-optional } -선택적으로 FastAPI 앱을 FastAPI Cloud에 배포할 수 있습니다. 아직이라면 대기자 명단에 등록해 보세요. 🚀 +선택적으로 FastAPI 앱을 [FastAPI Cloud](https://fastapicloud.com)에 배포할 수 있습니다. 아직이라면 대기자 명단에 등록해 보세요. 🚀 이미 **FastAPI Cloud** 계정이 있다면(대기자 명단에서 초대해 드렸습니다 😉), 한 번의 명령으로 애플리케이션을 배포할 수 있습니다. -배포하기 전에, 로그인되어 있는지 확인하세요: - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -그런 다음 앱을 배포하세요: -
```console @@ -488,7 +474,7 @@ Deploying to FastAPI Cloud... #### FastAPI Cloud 소개 { #about-fastapi-cloud } -**FastAPI Cloud**는 **FastAPI** 뒤에 있는 동일한 작성자와 팀이 만들었습니다. +**[FastAPI Cloud](https://fastapicloud.com)**는 **FastAPI** 뒤에 있는 동일한 작성자와 팀이 만들었습니다. 최소한의 노력으로 API를 **빌드**, **배포**, **접근**하는 과정을 간소화합니다. @@ -504,9 +490,9 @@ FastAPI는 오픈 소스이며 표준을 기반으로 합니다. 선택한 어 ## 성능 { #performance } -독립된 TechEmpower 벤치마크에서 Uvicorn에서 작동하는 FastAPI 애플리케이션이 사용 가능한 가장 빠른 Python 프레임워크 중 하나로 Starlette와 Uvicorn(FastAPI에서 내부적으로 사용)에만 밑돌고 있습니다. (*) +독립된 TechEmpower 벤치마크에서 Uvicorn에서 작동하는 **FastAPI** 애플리케이션이 [사용 가능한 가장 빠른 Python 프레임워크 중 하나](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7)로 Starlette와 Uvicorn(FastAPI에서 내부적으로 사용)에만 밑돌고 있습니다. (*) -자세한 내용은 벤치마크 섹션을 보십시오. +자세한 내용은 [벤치마크](https://fastapi.tiangolo.com/ko/benchmarks/) 섹션을 보십시오. ## 의존성 { #dependencies } @@ -514,23 +500,23 @@ FastAPI는 Pydantic과 Starlette에 의존합니다. ### `standard` 의존성 { #standard-dependencies } -FastAPI를 `pip install "fastapi[standard]"`로 설치하면 `standard` 그룹의 선택적 의존성이 함께 설치됩니다. +`pip install "fastapi[standard]"`로 FastAPI를 설치하면 `standard` 그룹의 선택적 의존성이 함께 설치됩니다. Pydantic이 사용하는: -* email-validator - 이메일 유효성 검사. +* [`email-validator`](https://github.com/JoshData/python-email-validator) - 이메일 유효성 검사. Starlette이 사용하는: -* httpx - `TestClient`를 사용하려면 필요. -* jinja2 - 기본 템플릿 설정을 사용하려면 필요. -* python-multipart - `request.form()`과 함께 form "파싱" 지원을 원하면 필요. +* [`httpx`](https://www.python-httpx.org) - `TestClient`를 사용하려면 필요. +* [`jinja2`](https://jinja.palletsprojects.com) - 기본 템플릿 설정을 사용하려면 필요. +* [`python-multipart`](https://github.com/Kludex/python-multipart) - `request.form()`과 함께 form "파싱" 지원을 원하면 필요. FastAPI가 사용하는: -* uvicorn - 애플리케이션을 로드하고 제공하는 서버를 위한 것입니다. 여기에는 고성능 서빙에 필요한 일부 의존성(예: `uvloop`)이 포함된 `uvicorn[standard]`가 포함됩니다. +* [`uvicorn`](https://www.uvicorn.dev) - 애플리케이션을 로드하고 제공하는 서버를 위한 것입니다. 여기에는 고성능 서빙에 필요한 일부 의존성(예: `uvloop`)이 포함된 `uvicorn[standard]`가 포함됩니다. * `fastapi-cli[standard]` - `fastapi` 명령을 제공하기 위한 것입니다. - * 여기에는 FastAPI 애플리케이션을 FastAPI Cloud에 배포할 수 있게 해주는 `fastapi-cloud-cli`가 포함됩니다. + * 여기에는 [FastAPI Cloud](https://fastapicloud.com)에 FastAPI 애플리케이션을 배포할 수 있게 해주는 `fastapi-cloud-cli`가 포함됩니다. ### `standard` 의존성 없이 { #without-standard-dependencies } @@ -546,13 +532,13 @@ FastAPI가 사용하는: 추가 선택적 Pydantic 의존성: -* pydantic-settings - 설정 관리를 위한 것입니다. -* pydantic-extra-types - Pydantic에서 사용할 추가 타입을 위한 것입니다. +* [`pydantic-settings`](https://docs.pydantic.dev/latest/usage/pydantic_settings/) - 설정 관리를 위한 것입니다. +* [`pydantic-extra-types`](https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/) - Pydantic에서 사용할 추가 타입을 위한 것입니다. 추가 선택적 FastAPI 의존성: -* orjson - `ORJSONResponse`를 사용하려면 필요. -* ujson - `UJSONResponse`를 사용하려면 필요. +* [`orjson`](https://github.com/ijl/orjson) - `ORJSONResponse`를 사용하려면 필요. +* [`ujson`](https://github.com/esnme/ultrajson) - `UJSONResponse`를 사용하려면 필요. ## 라이센스 { #license } diff --git a/docs/ko/docs/project-generation.md b/docs/ko/docs/project-generation.md index e3120e6f80..774b03a190 100644 --- a/docs/ko/docs/project-generation.md +++ b/docs/ko/docs/project-generation.md @@ -4,7 +4,7 @@ 많은 초기 설정, 보안, 데이터베이스 및 일부 API 엔드포인트가 이미 준비되어 있으므로, 여러분은 이 템플릿을 시작하는 데 사용할 수 있습니다. -GitHub 저장소: Full Stack FastAPI 템플릿 +GitHub 저장소: [Full Stack FastAPI 템플릿](https://github.com/tiangolo/full-stack-fastapi-template) ## Full Stack FastAPI 템플릿 - 기술 스택과 기능들 { #full-stack-fastapi-template-technology-stack-and-features } diff --git a/docs/ko/docs/python-types.md b/docs/ko/docs/python-types.md index d7d9021ed3..12890f2832 100644 --- a/docs/ko/docs/python-types.md +++ b/docs/ko/docs/python-types.md @@ -271,7 +271,7 @@ def some_function(data: Any): ## Pydantic 모델 { #pydantic-models } -Pydantic은 데이터 검증을 수행하는 파이썬 라이브러리입니다. +[Pydantic](https://docs.pydantic.dev/)은 데이터 검증을 수행하는 파이썬 라이브러리입니다. 속성을 가진 클래스 형태로 데이터의 "모양(shape)"을 선언합니다. @@ -287,13 +287,13 @@ Pydantic 공식 문서의 예시: /// info | 정보 -Pydantic에 대해 더 알아보려면 문서를 확인하세요. +Pydantic에 대해 더 알아보려면 [문서를 확인하세요](https://docs.pydantic.dev/). /// **FastAPI**는 모두 Pydantic에 기반을 두고 있습니다. -이 모든 것은 [자습서 - 사용자 안내서](tutorial/index.md){.internal-link target=_blank}에서 실제로 많이 보게 될 것입니다. +이 모든 것은 [자습서 - 사용자 안내서](tutorial/index.md)에서 실제로 많이 보게 될 것입니다. ## 메타데이터 애너테이션이 있는 타입 힌트 { #type-hints-with-metadata-annotations } @@ -339,12 +339,12 @@ Pydantic 공식 문서의 예시: * OpenAPI를 사용해 API를 **문서화**: * 자동 상호작용 문서 UI에서 사용됩니다. -이 모든 것이 다소 추상적으로 들릴 수도 있습니다. 걱정하지 마세요. [자습서 - 사용자 안내서](tutorial/index.md){.internal-link target=_blank}에서 실제로 확인하게 될 것입니다. +이 모든 것이 다소 추상적으로 들릴 수도 있습니다. 걱정하지 마세요. [자습서 - 사용자 안내서](tutorial/index.md)에서 실제로 확인하게 될 것입니다. 가장 중요한 점은 표준 파이썬 타입을 한 곳에서 사용함으로써(더 많은 클래스, 데코레이터 등을 추가하는 대신) **FastAPI**가 여러분을 위해 많은 일을 해준다는 사실입니다. /// info | 정보 -자습서를 모두 끝내고 타입에 대해 더 알아보기 위해 다시 돌아왔다면, 좋은 자료로 `mypy`의 "cheat sheet"가 있습니다. +자습서를 모두 끝내고 타입에 대해 더 알아보기 위해 다시 돌아왔다면, 좋은 자료로 [`mypy`의 "cheat sheet"](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html)가 있습니다. /// diff --git a/docs/ko/docs/tutorial/background-tasks.md b/docs/ko/docs/tutorial/background-tasks.md index f23902e11f..1f042829c0 100644 --- a/docs/ko/docs/tutorial/background-tasks.md +++ b/docs/ko/docs/tutorial/background-tasks.md @@ -63,7 +63,7 @@ FastAPI에서는 응답을 반환한 *후에* 실행할 백그라운드 작업 ## 기술적 세부사항 { #technical-details } -`BackgroundTasks` 클래스는 `starlette.background`에서 직접 가져옵니다. +`BackgroundTasks` 클래스는 [`starlette.background`](https://www.starlette.dev/background/)에서 직접 가져옵니다. FastAPI에 직접 임포트/포함되어 있으므로 `fastapi`에서 임포트할 수 있고, 실수로 `starlette.background`에서 대안인 `BackgroundTask`(끝에 `s`가 없음)를 임포트하는 것을 피할 수 있습니다. @@ -71,15 +71,15 @@ FastAPI에 직접 임포트/포함되어 있으므로 `fastapi`에서 임포트 FastAPI에서 `BackgroundTask`만 단독으로 사용하는 것도 가능하지만, 코드에서 객체를 생성하고 이를 포함하는 Starlette `Response`를 반환해야 합니다. -더 자세한 내용은 Starlette의 Background Tasks 공식 문서에서 확인할 수 있습니다. +더 자세한 내용은 [Starlette의 Background Tasks 공식 문서](https://www.starlette.dev/background/)에서 확인할 수 있습니다. ## 주의사항 { #caveat } -무거운 백그라운드 계산을 수행해야 하고, 반드시 동일한 프로세스에서 실행할 필요가 없다면(예: 메모리, 변수 등을 공유할 필요가 없음) Celery 같은 더 큰 도구를 사용하는 것이 도움이 될 수 있습니다. +무거운 백그라운드 계산을 수행해야 하고, 반드시 동일한 프로세스에서 실행할 필요가 없다면(예: 메모리, 변수 등을 공유할 필요가 없음) [Celery](https://docs.celeryq.dev) 같은 더 큰 도구를 사용하는 것이 도움이 될 수 있습니다. 이들은 RabbitMQ나 Redis 같은 메시지/작업 큐 관리자 등 더 복잡한 설정을 필요로 하는 경향이 있지만, 여러 프로세스에서, 특히 여러 서버에서 백그라운드 작업을 실행할 수 있습니다. -하지만 동일한 **FastAPI** 앱의 변수와 객체에 접근해야 하거나(또는 이메일 알림 전송처럼) 작은 백그라운드 작업을 수행해야 한다면, `BackgroundTasks`를 간단히 사용하면 됩니다. +하지만 동일한 **FastAPI** 앱의 변수와 객체에 접근해야 하거나, 작은 백그라운드 작업(예: 이메일 알림 전송)을 수행해야 한다면, `BackgroundTasks`를 간단히 사용하면 됩니다. ## 요약 { #recap } diff --git a/docs/ko/docs/tutorial/bigger-applications.md b/docs/ko/docs/tutorial/bigger-applications.md index 1b9d17e49a..5b93dbb20b 100644 --- a/docs/ko/docs/tutorial/bigger-applications.md +++ b/docs/ko/docs/tutorial/bigger-applications.md @@ -123,7 +123,7 @@ from app.routers import items 이 예시를 단순화하기 위해 임의로 만든 헤더를 사용하고 있습니다. -하지만 실제 상황에서는 통합된 [Security 유틸리티](security/index.md){.internal-link target=_blank}를 사용하는 것이 더 좋은 결과를 얻을 수 있습니다. +하지만 실제 상황에서는 통합된 [Security 유틸리티](security/index.md)를 사용하는 것이 더 좋은 결과를 얻을 수 있습니다. /// @@ -169,7 +169,7 @@ async def read_item(item_id: str): /// tip | 팁 -[*path operation decorator의 dependencies*](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}와 마찬가지로, *path operation function*에 어떤 값도 전달되지 않습니다. +[*path operation decorator의 dependencies*](dependencies/dependencies-in-path-operation-decorators.md)와 마찬가지로, *path operation function*에 어떤 값도 전달되지 않습니다. /// @@ -185,8 +185,8 @@ async def read_item(item_id: str): * 모두 미리 정의된 `responses`를 포함합니다. * 이 모든 *path operations*는 실행되기 전에 `dependencies` 목록이 평가/실행됩니다. * 특정 *path operation*에 dependencies를 추가로 선언하면 **그것들도 실행됩니다**. - * router dependencies가 먼저 실행되고, 그 다음에 [decorator의 `dependencies`](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, 그리고 일반 파라미터 dependencies가 실행됩니다. - * [`scopes`가 있는 `Security` dependencies](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}도 추가할 수 있습니다. + * router dependencies가 먼저 실행되고, 그 다음에 [decorator의 `dependencies`](dependencies/dependencies-in-path-operation-decorators.md), 그리고 일반 파라미터 dependencies가 실행됩니다. + * [`scopes`가 있는 `Security` dependencies](../advanced/security/oauth2-scopes.md)도 추가할 수 있습니다. /// tip | 팁 @@ -303,7 +303,7 @@ from ...dependencies import get_token_header 평소처럼 `FastAPI` 클래스를 import하고 생성합니다. -또한 각 `APIRouter`의 dependencies와 결합될 [global dependencies](dependencies/global-dependencies.md){.internal-link target=_blank}도 선언할 수 있습니다: +또한 각 `APIRouter`의 dependencies와 결합될 [global dependencies](dependencies/global-dependencies.md)도 선언할 수 있습니다: {* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} @@ -353,7 +353,7 @@ from .routers import items, users from app.routers import items, users ``` -Python Packages와 Modules에 대해 더 알아보려면 Modules에 대한 Python 공식 문서를 읽어보세요. +Python Packages와 Modules에 대해 더 알아보려면 [Modules에 대한 Python 공식 문서](https://docs.python.org/3/tutorial/modules.html)를 읽어보세요. /// @@ -465,6 +465,37 @@ router를 포함(include)할 때 성능을 걱정할 필요는 없습니다. /// +## `pyproject.toml`에서 `entrypoint` 구성하기 { #configure-the-entrypoint-in-pyproject-toml } + +FastAPI `app` 객체가 `app/main.py`에 있으므로 `pyproject.toml` 파일에서 `entrypoint`를 다음과 같이 구성할 수 있습니다: + +```toml +[tool.fastapi] +entrypoint = "app.main:app" +``` + +이는 다음과 같이 import하는 것과 동일합니다: + +```python +from app.main import app +``` + +이렇게 하면 `fastapi` 명령어가 여러분의 앱이 어디에 있는지 알 수 있습니다. + +/// Note | 참고 + +명령어에 경로를 직접 전달할 수도 있습니다: + +```console +$ fastapi dev app/main.py +``` + +하지만 `fastapi` 명령어를 실행할 때마다 올바른 경로를 기억해 전달해야 합니다. + +또한 [VS Code 확장](../editor-support.md)이나 [FastAPI Cloud](https://fastapicloud.com) 같은 다른 도구들이 이를 찾지 못할 수도 있으므로, `pyproject.toml`의 `entrypoint`를 사용하는 것을 권장합니다. + +/// + ## 자동 API 문서 확인하기 { #check-the-automatic-api-docs } 이제 앱을 실행하세요: @@ -472,14 +503,14 @@ router를 포함(include)할 때 성능을 걱정할 필요는 없습니다.
```console -$ fastapi dev app/main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-그리고 http://127.0.0.1:8000/docs에서 문서를 여세요. +그리고 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)에서 문서를 여세요. 올바른 경로(및 prefix)와 올바른 태그를 사용해, 모든 submodule의 경로를 포함한 자동 API 문서를 볼 수 있습니다: diff --git a/docs/ko/docs/tutorial/body-nested-models.md b/docs/ko/docs/tutorial/body-nested-models.md index 33f0f71e95..bbb95cf00b 100644 --- a/docs/ko/docs/tutorial/body-nested-models.md +++ b/docs/ko/docs/tutorial/body-nested-models.md @@ -96,7 +96,7 @@ Pydantic 모델의 각 어트리뷰트는 타입을 갖습니다. `str`, `int`, `float` 등과 같은 일반적인 단일 타입과는 별개로, `str`을 상속하는 더 복잡한 단일 타입을 사용할 수 있습니다. -사용할 수 있는 모든 옵션을 보려면 Pydantic의 Type Overview를 확인하세요. 다음 장에서 몇 가지 예제를 볼 수 있습니다. +사용할 수 있는 모든 옵션을 보려면 [Pydantic의 Type Overview](https://docs.pydantic.dev/latest/concepts/types/)를 확인하세요. 다음 장에서 몇 가지 예제를 볼 수 있습니다. 예를 들어 `Image` 모델에는 `url` 필드가 있으므로, 이를 `str` 대신 Pydantic의 `HttpUrl` 인스턴스로 선언할 수 있습니다: diff --git a/docs/ko/docs/tutorial/body-updates.md b/docs/ko/docs/tutorial/body-updates.md index 3719e1ffab..f9ea061a6e 100644 --- a/docs/ko/docs/tutorial/body-updates.md +++ b/docs/ko/docs/tutorial/body-updates.md @@ -2,7 +2,7 @@ ## `PUT`으로 교체 업데이트하기 { #update-replacing-with-put } -항목을 업데이트하려면 HTTP `PUT` 작업을 사용할 수 있습니다. +항목을 업데이트하려면 [HTTP `PUT`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) 작업을 사용할 수 있습니다. `jsonable_encoder`를 사용해 입력 데이터를 JSON으로 저장할 수 있는 데이터로 변환할 수 있습니다(예: NoSQL 데이터베이스 사용 시). 예를 들어 `datetime`을 `str`로 변환하는 경우입니다. @@ -28,7 +28,7 @@ ## `PATCH`로 부분 업데이트하기 { #partial-updates-with-patch } -HTTP `PATCH` 작업을 사용해 데이터를 *부분적으로* 업데이트할 수도 있습니다. +[HTTP `PATCH`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) 작업을 사용해 데이터를 *부분적으로* 업데이트할 수도 있습니다. 이는 업데이트하려는 데이터만 보내고, 나머지는 그대로 두는 것을 의미합니다. @@ -95,6 +95,6 @@ 따라서 모든 속성을 생략할 수 있는 부분 업데이트를 받으려면, 모든 속성이 optional로 표시된(기본값을 가지거나 `None`을 기본값으로 가지는) 모델이 필요합니다. -**업데이트**를 위한 “모든 값이 optional인” 모델과, **생성**을 위한 “필수 값이 있는” 모델을 구분하려면 [추가 모델](extra-models.md){.internal-link target=_blank}에 설명된 아이디어를 사용할 수 있습니다. +**업데이트**를 위한 “모든 값이 optional인” 모델과, **생성**을 위한 “필수 값이 있는” 모델을 구분하려면 [추가 모델](extra-models.md)에 설명된 아이디어를 사용할 수 있습니다. /// diff --git a/docs/ko/docs/tutorial/body.md b/docs/ko/docs/tutorial/body.md index b282d1cc92..d124b4bef0 100644 --- a/docs/ko/docs/tutorial/body.md +++ b/docs/ko/docs/tutorial/body.md @@ -6,7 +6,7 @@ 여러분의 API는 대부분의 경우 **응답** 본문을 보내야 합니다. 하지만 클라이언트는 항상 **요청 본문**을 보낼 필요는 없고, 때로는 (쿼리 매개변수와 함께) 어떤 경로만 요청하고 본문은 보내지 않을 수도 있습니다. -**요청** 본문을 선언하기 위해서 모든 강력함과 이점을 갖춘 Pydantic 모델을 사용합니다. +**요청** 본문을 선언하기 위해서 모든 강력함과 이점을 갖춘 [Pydantic](https://docs.pydantic.dev/) 모델을 사용합니다. /// info | 정보 @@ -73,7 +73,7 @@ * 만약 데이터가 유효하지 않다면, 정확히 어떤 것이 그리고 어디에서 데이터가 잘 못 되었는지 지시하는 친절하고 명료한 에러를 반환할 것입니다. * 매개변수 `item`에 포함된 수신 데이터를 제공합니다. * 함수 내에서 매개변수를 `Item` 타입으로 선언했기 때문에, 모든 어트리뷰트와 그에 대한 타입에 대한 편집기 지원(완성 등)을 또한 받을 수 있습니다. -* 여러분의 모델을 위한 JSON Schema 정의를 생성합니다. 여러분의 프로젝트에 적합하다면 여러분이 사용하고 싶은 곳 어디에서나 사용할 수 있습니다. +* 여러분의 모델을 위한 [JSON Schema](https://json-schema.org) 정의를 생성합니다. 여러분의 프로젝트에 적합하다면 여러분이 사용하고 싶은 곳 어디에서나 사용할 수 있습니다. * 이러한 스키마는, 생성된 OpenAPI 스키마 일부가 될 것이며, 자동 문서화 UIs에 사용됩니다. ## 자동 문서화 { #automatic-docs } @@ -102,15 +102,15 @@ 이를 지원하기 위해 Pydantic 자체에서 몇몇 변경점이 있었습니다. -이전 스크린샷은 Visual Studio Code를 찍은 것입니다. +이전 스크린샷은 [Visual Studio Code](https://code.visualstudio.com)로 찍은 것입니다. -하지만 똑같은 편집기 지원을 PyCharm와 대부분의 다른 파이썬 편집기에서도 받을 수 있습니다: +하지만 똑같은 편집기 지원을 [PyCharm](https://www.jetbrains.com/pycharm/)와 대부분의 다른 파이썬 편집기에서도 받을 수 있습니다: /// tip | 팁 -만약 PyCharm를 편집기로 사용한다면, Pydantic PyCharm Plugin을 사용할 수 있습니다. +만약 [PyCharm](https://www.jetbrains.com/pycharm/)를 편집기로 사용한다면, [Pydantic PyCharm Plugin](https://github.com/koxudaxi/pydantic-pycharm-plugin/)을 사용할 수 있습니다. 다음 사항을 포함해 Pydantic 모델에 대한 편집기 지원을 향상시킵니다: @@ -163,4 +163,4 @@ FastAPI는 `q`의 값이 필요없음을 기본 값 `= None` 때문에 알게 ## Pydantic없이 { #without-pydantic } -만약 Pydantic 모델을 사용하고 싶지 않다면, **Body** 매개변수를 사용할 수도 있습니다. [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank} 문서를 확인하세요. +만약 Pydantic 모델을 사용하고 싶지 않다면, **Body** 매개변수를 사용할 수도 있습니다. [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body) 문서를 확인하세요. diff --git a/docs/ko/docs/tutorial/cors.md b/docs/ko/docs/tutorial/cors.md index f78e1c0707..08d0221d3d 100644 --- a/docs/ko/docs/tutorial/cors.md +++ b/docs/ko/docs/tutorial/cors.md @@ -1,6 +1,6 @@ # CORS (교차-출처 리소스 공유) { #cors-cross-origin-resource-sharing } -CORS 또는 "Cross-Origin Resource Sharing"란, 브라우저에서 실행되는 프론트엔드에 백엔드와 통신하는 JavaScript 코드가 있고, 백엔드가 프론트엔드와 다른 "출처(origin)"에 있는 상황을 의미합니다. +[CORS 또는 "Cross-Origin Resource Sharing"](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)란, 브라우저에서 실행되는 프론트엔드에 백엔드와 통신하는 JavaScript 코드가 있고, 백엔드가 프론트엔드와 다른 "출처(origin)"에 있는 상황을 의미합니다. ## 출처 { #origin } @@ -56,10 +56,10 @@ * `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_headers` - 교차-출처 요청에 대해 지원되어야 하는 HTTP 요청 헤더의 리스트입니다. 기본값은 `[]`입니다. 모든 헤더를 허용하려면 `['*']`를 사용할 수 있습니다. `Accept`, `Accept-Language`, `Content-Language`, `Content-Type` 헤더는 [단순 CORS 요청](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests)에 대해 항상 허용됩니다. * `allow_credentials` - 교차-출처 요청에 대해 쿠키를 지원해야 함을 나타냅니다. 기본값은 `False`입니다. - `allow_credentials`가 `True`로 설정된 경우 `allow_origins`, `allow_methods`, `allow_headers` 중 어느 것도 `['*']`로 설정할 수 없습니다. 모두 명시적으로 지정되어야 합니다. + `allow_credentials`가 `True`로 설정된 경우 `allow_origins`, `allow_methods`, `allow_headers` 중 어느 것도 `['*']`로 설정할 수 없습니다. 모두 [명시적으로 지정](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards)되어야 합니다. * `expose_headers` - 브라우저에서 접근 가능해야 하는 모든 응답 헤더를 나타냅니다. 기본값은 `[]`입니다. * `max_age` - 브라우저가 CORS 응답을 캐시하는 최대 시간을 초 단위로 설정합니다. 기본값은 `600`입니다. @@ -78,7 +78,7 @@ ## 더 많은 정보 { #more-info } -CORS에 대한 더 많은 정보는 Mozilla CORS 문서를 참고하세요. +CORS에 대한 더 많은 정보는 [Mozilla CORS 문서](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)를 참고하세요. /// note | 기술 세부사항 diff --git a/docs/ko/docs/tutorial/debugging.md b/docs/ko/docs/tutorial/debugging.md index c27b68bc1c..145ffb24bc 100644 --- a/docs/ko/docs/tutorial/debugging.md +++ b/docs/ko/docs/tutorial/debugging.md @@ -74,7 +74,7 @@ from myapp import app /// info | 정보 -자세한 내용은 공식 Python 문서를 확인하세요. +자세한 내용은 [공식 Python 문서](https://docs.python.org/3/library/__main__.html)를 확인하세요. /// diff --git a/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index d269e7e774..880a47157f 100644 --- a/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -32,7 +32,7 @@ 이 예시에서 `X-Key`와 `X-Token`이라는 커스텀 헤더를 만들어 사용했습니다. -그러나 실제로 보안을 구현할 때는 통합된 [보안 유틸리티 (다음 챕터)](../security/index.md){.internal-link target=_blank}를 사용하는 것이 더 많은 이점을 얻을 수 있습니다. +그러나 실제로 보안을 구현할 때는 통합된 [보안 유틸리티 (다음 챕터)](../security/index.md)를 사용하는 것이 더 많은 이점을 얻을 수 있습니다. /// @@ -62,7 +62,7 @@ ## *경로 처리* 모음에 대한 의존성 { #dependencies-for-a-group-of-path-operations } -나중에 여러 파일을 가지고 있을 수 있는 더 큰 애플리케이션을 구조화하는 법([더 큰 애플리케이션 - 여러 파일들](../../tutorial/bigger-applications.md){.internal-link target=_blank})을 읽을 때, *경로 처리* 모음에 대한 단일 `dependencies` 매개변수를 선언하는 법에 대해서 배우게 될 것입니다. +나중에 여러 파일을 가지고 있을 수 있는 더 큰 애플리케이션을 구조화하는 법([더 큰 애플리케이션 - 여러 파일들](../../tutorial/bigger-applications.md))을 읽을 때, *경로 처리* 모음에 대한 단일 `dependencies` 매개변수를 선언하는 법에 대해서 배우게 될 것입니다. ## 전역 의존성 { #global-dependencies } diff --git a/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md index 7b50fd438b..56f690f593 100644 --- a/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md @@ -4,7 +4,7 @@ FastAPI는 `@contextlib.contextmanager` 또는 -* `@contextlib.asynccontextmanager` +* [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) 또는 +* [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) 는 **FastAPI**의 의존성으로 사용할 수 있습니다. @@ -39,7 +39,7 @@ yield된 값은 *경로 처리* 및 다른 의존성들에 주입되는 값 입 {* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *} -/// tip | 팁 +/// tip `async` 함수와 일반 함수 모두 사용할 수 있습니다. @@ -87,7 +87,7 @@ yield된 값은 *경로 처리* 및 다른 의존성들에 주입되는 값 입 /// note | 기술 세부사항 -파이썬의 Context Managers 덕분에 이 기능이 작동합니다. +파이썬의 [Context Managers](https://docs.python.org/3/library/contextlib.html) 덕분에 이 기능이 작동합니다. **FastAPI**는 이를 내부적으로 사용하여 이를 달성합니다. @@ -101,7 +101,7 @@ yield된 값은 *경로 처리* 및 다른 의존성들에 주입되는 값 입 예를 들어, `HTTPException` 같은 다른 예외를 발생시킬 수 있습니다. -/// tip | 팁 +/// tip 이는 다소 고급 기술이며, 대부분의 경우 실제로는 필요하지 않을 것입니다. 예를 들어, *경로 처리 함수* 등 나머지 애플리케이션 코드 내부에서 예외 (`HTTPException` 포함)를 발생시킬 수 있기 때문입니다. @@ -111,7 +111,7 @@ yield된 값은 *경로 처리* 및 다른 의존성들에 주입되는 값 입 {* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} -예외를 잡고 그에 기반해 사용자 정의 응답을 생성하려면, [사용자 정의 예외 처리기](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}를 생성하세요. +예외를 잡고 그에 기반해 사용자 정의 응답을 생성하려면, [사용자 정의 예외 처리기](../handling-errors.md#install-custom-exception-handlers)를 생성하세요. ## `yield`와 `except`를 사용하는 의존성 { #dependencies-with-yield-and-except } @@ -170,7 +170,7 @@ participant tasks as Background tasks end ``` -/// info | 정보 +/// info 클라이언트에는 **하나의 응답**만 전송됩니다. 이는 오류 응답 중 하나일 수도 있고, *경로 처리*에서 생성된 응답일 수도 있습니다. @@ -178,7 +178,7 @@ participant tasks as Background tasks /// -/// tip | 팁 +/// tip *경로 처리 함수*의 코드에서 어떤 예외를 발생시키면 `HTTPException`을 포함해 `yield`를 사용하는 의존성으로 전달됩니다. 대부분의 경우 해당 예외(또는 새 예외)를 `yield`를 사용하는 의존성에서 다시 발생시켜, 제대로 처리되도록 해야 합니다. @@ -233,14 +233,14 @@ participant operation as Path Operation `yield`를 사용하는 의존성은 시간이 지나면서 서로 다른 사용 사례를 다루고 일부 문제를 수정하기 위해 발전해 왔습니다. -FastAPI의 여러 버전에서 무엇이 바뀌었는지 보고 싶다면, 고급 가이드의 [고급 의존성 - `yield`, `HTTPException`, `except` 및 백그라운드 작업을 사용하는 의존성](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}에서 더 자세히 읽을 수 있습니다. +FastAPI의 여러 버전에서 무엇이 바뀌었는지 보고 싶다면, 고급 가이드의 [고급 의존성 - `yield`, `HTTPException`, `except` 및 백그라운드 작업을 사용하는 의존성](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks)에서 더 자세히 읽을 수 있습니다. ## 컨텍스트 관리자 { #context-managers } ### "컨텍스트 관리자"란 { #what-are-context-managers } "컨텍스트 관리자"는 Python에서 `with` 문에서 사용할 수 있는 모든 객체를 의미합니다. -예를 들어, `with`를 사용하여 파일을 읽을 수 있습니다: +예를 들어, [with를 사용해 파일을 읽을 수 있습니다](https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files): ```Python with open("./somefile.txt") as f: @@ -256,7 +256,7 @@ with open("./somefile.txt") as f: ### `yield`를 사용하는 의존성에서 컨텍스트 관리자 사용하기 { #using-context-managers-in-dependencies-with-yield } -/// warning | 경고 +/// warning 이것은 어느 정도 "고급" 개념입니다. @@ -264,19 +264,19 @@ with open("./somefile.txt") as f: /// -Python에서는 다음을 통해 컨텍스트 관리자를 생성할 수 있습니다. 두 가지 메서드가 있는 클래스를 생성합니다: `__enter__()` and `__exit__()`. +Python에서는 [두 가지 메서드: `__enter__()`와 `__exit__()`가 있는 클래스를 생성하여](https://docs.python.org/3/reference/datamodel.html#context-managers) 컨텍스트 관리자를 만들 수 있습니다. **FastAPI**의 `yield`가 있는 의존성 내에서 `with` 또는 `async with`문을 사용하여 이들을 활용할 수 있습니다: {* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *} -/// tip | 팁 +/// tip 컨텍스트 관리자를 생성하는 또 다른 방법은 다음과 같습니다: -* `@contextlib.contextmanager` 또는 -* `@contextlib.asynccontextmanager` +* [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) 또는 +* [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) 이들은 단일 `yield`가 있는 함수를 꾸미는 데 사용합니다. diff --git a/docs/ko/docs/tutorial/dependencies/global-dependencies.md b/docs/ko/docs/tutorial/dependencies/global-dependencies.md index 8b000a3a43..6d4c43eb6c 100644 --- a/docs/ko/docs/tutorial/dependencies/global-dependencies.md +++ b/docs/ko/docs/tutorial/dependencies/global-dependencies.md @@ -2,14 +2,14 @@ 몇몇 유형의 애플리케이션에서는 애플리케이션 전체에 의존성을 추가하고 싶을 수 있습니다. -[*경로 처리 데코레이터*에 `dependencies` 추가하기](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}와 유사한 방법으로 `FastAPI` 애플리케이션에 그것들을 추가할 수 있습니다. +[*경로 처리 데코레이터*에 `dependencies` 추가하기](dependencies-in-path-operation-decorators.md)와 유사한 방법으로 `FastAPI` 애플리케이션에 그것들을 추가할 수 있습니다. 그런 경우에, 애플리케이션의 모든 *경로 처리*에 적용될 것입니다: {* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *} -그리고 [*경로 처리 데코레이터*에 `dependencies` 추가하기](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} 섹션의 모든 아이디어는 여전히 적용되지만, 이 경우에는 앱의 모든 *경로 처리*에 적용됩니다. +그리고 [*경로 처리 데코레이터*에 `dependencies` 추가하기](dependencies-in-path-operation-decorators.md) 섹션의 모든 아이디어는 여전히 적용되지만, 이 경우에는 애플리케이션의 모든 *경로 처리*에 적용됩니다. ## *경로 처리* 그룹에 대한 의존성 { #dependencies-for-groups-of-path-operations } -나중에 여러 파일을 포함할 수도 있는 더 큰 애플리케이션을 구조화하는 법([더 큰 애플리케이션 - 여러 파일들](../../tutorial/bigger-applications.md){.internal-link target=_blank})을 읽을 때, *경로 처리* 그룹에 대한 단일 `dependencies` 매개변수를 선언하는 법을 배우게 될 것입니다. +나중에 여러 파일을 포함할 수도 있는 더 큰 애플리케이션을 구조화하는 법([더 큰 애플리케이션 - 여러 파일들](../../tutorial/bigger-applications.md))을 읽을 때, *경로 처리* 그룹에 대한 단일 `dependencies` 매개변수를 선언하는 법을 배우게 될 것입니다. diff --git a/docs/ko/docs/tutorial/dependencies/index.md b/docs/ko/docs/tutorial/dependencies/index.md index f7d8d5982c..4b540b779e 100644 --- a/docs/ko/docs/tutorial/dependencies/index.md +++ b/docs/ko/docs/tutorial/dependencies/index.md @@ -57,7 +57,7 @@ FastAPI는 0.95.0 버전부터 `Annotated`에 대한 지원을 (그리고 이를 옛날 버전을 가지고 있는 경우, `Annotated`를 사용하려 하면 에러를 맞이하게 될 것입니다. -`Annotated`를 사용하기 전에 최소 0.95.1로 [FastAPI 버전 업그레이드](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}를 확실하게 하세요. +`Annotated`를 사용하기 전에 최소 0.95.1로 [FastAPI 버전 업그레이드](../../deployment/versions.md#upgrading-the-fastapi-versions)를 확실하게 하세요. /// @@ -152,7 +152,7 @@ commons: Annotated[dict, Depends(common_parameters)] /// note | 참고 -잘 모르시겠다면, [Async: *"In a hurry?"*](../../async.md#in-a-hurry){.internal-link target=_blank} 문서에서 `async`와 `await`에 대해 확인할 수 있습니다. +잘 모르시겠다면, [Async: *"In a hurry?"*](../../async.md#in-a-hurry) 문서에서 `async`와 `await`에 대해 확인할 수 있습니다. /// diff --git a/docs/ko/docs/tutorial/encoder.md b/docs/ko/docs/tutorial/encoder.md index d820f6e44d..9ed7a13cd8 100644 --- a/docs/ko/docs/tutorial/encoder.md +++ b/docs/ko/docs/tutorial/encoder.md @@ -12,7 +12,7 @@ JSON 호환 가능 데이터만 수신하는 `fake_db` 데이터베이스가 존 예를 들면, `datetime` 객체는 JSON과 호환되지 않으므로 이 데이터베이스는 이를 받지 않습니다. -따라서 `datetime` 객체는 ISO 형식의 데이터를 포함하는 `str`로 변환되어야 합니다. +따라서 `datetime` 객체는 [ISO 형식](https://en.wikipedia.org/wiki/ISO_8601)의 데이터를 포함하는 `str`로 변환되어야 합니다. 같은 방식으로 이 데이터베이스는 Pydantic 모델(속성이 있는 객체)을 받지 않고, `dict`만을 받습니다. @@ -24,7 +24,7 @@ Pydantic 모델 같은 객체를 받고 JSON 호환 가능한 버전을 반환 이 예시에서는 Pydantic 모델을 `dict`로, `datetime`을 `str`로 변환합니다. -이렇게 호출한 결과는 파이썬 표준인 `json.dumps()`로 인코딩할 수 있습니다. +이렇게 호출한 결과는 파이썬 표준인 [`json.dumps()`](https://docs.python.org/3/library/json.html#json.dumps)로 인코딩할 수 있습니다. JSON 형식(문자열)의 데이터가 들어있는 큰 `str`을 반환하지 않습니다. JSON과 모두 호환되는 값과 하위 값이 있는 파이썬 표준 데이터 구조(예: `dict`)를 반환합니다. diff --git a/docs/ko/docs/tutorial/extra-data-types.md b/docs/ko/docs/tutorial/extra-data-types.md index 4a51e92861..da62a39927 100644 --- a/docs/ko/docs/tutorial/extra-data-types.md +++ b/docs/ko/docs/tutorial/extra-data-types.md @@ -36,7 +36,7 @@ * `datetime.timedelta`: * 파이썬의 `datetime.timedelta`. * 요청과 응답에서 전체 초(seconds)의 `float`로 표현됩니다. - * Pydantic은 "ISO 8601 time diff encoding"으로 표현하는 것 또한 허용합니다. 더 많은 정보는 문서를 확인하세요. + * Pydantic은 "ISO 8601 time diff encoding"으로 표현하는 것 또한 허용합니다. [더 많은 정보는 문서를 확인하세요](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). * `frozenset`: * 요청과 응답에서 `set`와 동일하게 취급됩니다: * 요청 시, 리스트를 읽어 중복을 제거하고 `set`로 변환합니다. @@ -49,7 +49,7 @@ * `Decimal`: * 표준 파이썬의 `Decimal`. * 요청과 응답에서 `float`와 동일하게 다뤄집니다. -* 여기에서 모든 유효한 Pydantic 데이터 자료형을 확인할 수 있습니다: Pydantic 데이터 자료형. +* 여기에서 모든 유효한 Pydantic 데이터 자료형을 확인할 수 있습니다: [Pydantic 데이터 자료형](https://docs.pydantic.dev/latest/usage/types/types/). ## 예시 { #example } diff --git a/docs/ko/docs/tutorial/extra-models.md b/docs/ko/docs/tutorial/extra-models.md index 70d7f8bffc..157549f92f 100644 --- a/docs/ko/docs/tutorial/extra-models.md +++ b/docs/ko/docs/tutorial/extra-models.md @@ -12,7 +12,7 @@ 절대 사용자의 비밀번호를 평문으로 저장하지 마세요. 항상 이후에 검증 가능한 "안전한 해시(secure hash)"로 저장하세요. -만약 이게 무엇인지 모르겠다면, [보안 장](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}에서 "password hash"가 무엇인지 배울 수 있습니다. +만약 이게 무엇인지 모르겠다면, [보안 장](security/simple-oauth2.md#password-hashing)에서 "password hash"가 무엇인지 배울 수 있습니다. /// @@ -162,11 +162,11 @@ UserInDB( OpenAPI에서는 이를 `anyOf`로 정의합니다. -이를 위해 표준 Python 타입 힌트인 `typing.Union`을 사용할 수 있습니다: +이를 위해 표준 Python 타입 힌트인 [`typing.Union`](https://docs.python.org/3/library/typing.html#typing.Union)을 사용할 수 있습니다: /// note -`Union`을 정의할 때는 더 구체적인 타입을 먼저 포함하고, 덜 구체적인 타입을 그 뒤에 나열해야 합니다. 아래 예제에서는 `Union[PlaneItem, CarItem]`에서 더 구체적인 `PlaneItem`이 `CarItem`보다 앞에 위치합니다. +[`Union`](https://docs.pydantic.dev/latest/concepts/types/#unions)을 정의할 때는 더 구체적인 타입을 먼저 포함하고, 덜 구체적인 타입을 그 뒤에 나열해야 합니다. 아래 예제에서는 `Union[PlaneItem, CarItem]`에서 더 구체적인 `PlaneItem`이 `CarItem`보다 앞에 위치합니다. /// diff --git a/docs/ko/docs/tutorial/first-steps.md b/docs/ko/docs/tutorial/first-steps.md index e3d372ba42..cc3d6c6182 100644 --- a/docs/ko/docs/tutorial/first-steps.md +++ b/docs/ko/docs/tutorial/first-steps.md @@ -11,7 +11,7 @@
```console -$ fastapi dev main.py +$ fastapi dev FastAPI Starting development server 🚀 @@ -58,7 +58,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ### 확인하기 { #check-it } -브라우저로 http://127.0.0.1:8000를 여세요. +브라우저로 [http://127.0.0.1:8000](http://127.0.0.1:8000)를 여세요. 아래와 같은 JSON 응답을 볼 수 있습니다: @@ -68,17 +68,17 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ### 대화형 API 문서 { #interactive-api-docs } -이제 http://127.0.0.1:8000/docs로 가봅니다. +이제 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)로 가봅니다. -자동 대화형 API 문서를 볼 수 있습니다 (Swagger UI 제공): +자동 대화형 API 문서를 볼 수 있습니다 ([Swagger UI](https://github.com/swagger-api/swagger-ui) 제공): ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) ### 대안 API 문서 { #alternative-api-docs } -그리고 이제, http://127.0.0.1:8000/redoc로 가봅니다. +그리고 이제, [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)로 가봅니다. -대안 자동 문서를 볼 수 있습니다 (ReDoc 제공): +대안 자동 문서를 볼 수 있습니다 ([ReDoc](https://github.com/Rebilly/ReDoc) 제공): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -92,7 +92,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) #### API "스키마" { #api-schema } -OpenAPI는 API의 스키마를 어떻게 정의하는지 지시하는 규격입니다. +이 경우, [OpenAPI](https://github.com/OAI/OpenAPI-Specification)는 여러분의 API 스키마를 어떻게 정의하는지 지시하는 규격입니다. 이 스키마 정의는 API 경로, 가능한 매개변수 등을 포함합니다. @@ -110,7 +110,7 @@ OpenAPI는 여러분의 API에 대한 API 스키마를 정의합니다. 또한 가공되지 않은 OpenAPI 스키마가 어떻게 생겼는지 궁금하다면, FastAPI는 자동으로 여러분의 모든 API에 대한 설명과 함께 JSON (스키마)를 생성합니다. -여기에서 직접 볼 수 있습니다: http://127.0.0.1:8000/openapi.json. +여기에서 직접 볼 수 있습니다: [http://127.0.0.1:8000/openapi.json](http://127.0.0.1:8000/openapi.json). 다음과 같이 시작하는 JSON을 확인할 수 있습니다: @@ -143,9 +143,58 @@ OpenAPI 스키마는 포함된 두 개의 대화형 문서 시스템을 제공 API와 통신하는 클라이언트(프론트엔드, 모바일, IoT 애플리케이션 등)를 위해 코드를 자동으로 생성하는 데도 사용할 수 있습니다. +### `pyproject.toml`에 앱 `entrypoint` 구성하기 { #configure-the-app-entrypoint-in-pyproject-toml } + +다음과 같이 `pyproject.toml` 파일에서 앱이 위치한 곳을 구성할 수 있습니다: + +```toml +[tool.fastapi] +entrypoint = "main:app" +``` + +해당 `entrypoint`는 `fastapi` 명령어에 다음과 같이 앱을 임포트하라고 알려줍니다: + +```python +from main import app +``` + +코드 구조가 다음과 같다면: + +``` +. +├── backend +│   ├── main.py +│   ├── __init__.py +``` + +그럼 `entrypoint`를 다음과 같이 설정합니다: + +```toml +[tool.fastapi] +entrypoint = "backend.main:app" +``` + +이는 다음과 동일합니다: + +```python +from backend.main import app +``` + +### `fastapi dev`에 경로 지정하기 { #fastapi-dev-with-path } + +`fastapi dev` 명령어에 파일 경로를 전달할 수도 있으며, 그러면 사용할 FastAPI app 객체를 추정합니다: + +```console +$ fastapi dev main.py +``` + +하지만 매번 `fastapi` 명령어를 호출할 때마다 올바른 경로를 전달해야 합니다. + +또한 다른 도구들, 예를 들어 [VS Code 확장](../editor-support.md)이나 [FastAPI Cloud](https://fastapicloud.com)가 이를 찾지 못할 수 있으므로, `pyproject.toml`의 `entrypoint`를 사용하는 것을 권장합니다. + ### 앱 배포하기(선택 사항) { #deploy-your-app-optional } -선택적으로 FastAPI 앱을 FastAPI Cloud에 배포할 수 있습니다. 아직 대기자 명단에 등록하지 않았다면, 등록하러 가세요. 🚀 +선택적으로 FastAPI 앱을 [FastAPI Cloud](https://fastapicloud.com)에 배포할 수 있습니다. 아직 대기자 명단에 등록하지 않았다면, 등록하러 가세요. 🚀 이미 **FastAPI Cloud** 계정이 있다면(대기자 명단에서 초대해 드렸습니다 😉), 한 번의 명령으로 애플리케이션을 배포할 수 있습니다. @@ -191,7 +240,7 @@ Deploying to FastAPI Cloud... `FastAPI`는 `Starlette`를 직접 상속하는 클래스입니다. -`FastAPI`로 Starlette의 모든 기능을 사용할 수 있습니다. +`FastAPI`로 [Starlette](https://www.starlette.dev/)의 모든 기능을 사용할 수 있습니다. /// @@ -336,7 +385,7 @@ URL "`/`"에 대한 `GET` 작동을 사용하는 요청을 받을 때마다 **Fa /// note | 참고 -차이점을 모르겠다면 [Async: *"바쁘신 경우"*](../async.md#in-a-hurry){.internal-link target=_blank}를 확인하세요. +차이점을 모르겠다면 [Async: *"바쁘신 경우"*](../async.md#in-a-hurry)를 확인하세요. /// @@ -352,11 +401,11 @@ JSON으로 자동 변환되는 객체들과 모델들(ORM 등을 포함해서) ### 6 단계: 배포하기 { #step-6-deploy-it } -한 번의 명령으로 **FastAPI Cloud**에 앱을 배포합니다: `fastapi deploy`. 🎉 +한 번의 명령으로 **[FastAPI Cloud](https://fastapicloud.com)**에 앱을 배포합니다: `fastapi deploy`. 🎉 #### FastAPI Cloud 소개 { #about-fastapi-cloud } -**FastAPI Cloud**는 **FastAPI** 뒤에 있는 동일한 작성자와 팀이 만들었습니다. +**[FastAPI Cloud](https://fastapicloud.com)**는 **FastAPI** 뒤에 있는 동일한 작성자와 팀이 만들었습니다. 최소한의 노력으로 API를 **빌드**, **배포**, **접근**하는 과정을 간소화합니다. diff --git a/docs/ko/docs/tutorial/handling-errors.md b/docs/ko/docs/tutorial/handling-errors.md index 115c322363..efee108ef1 100644 --- a/docs/ko/docs/tutorial/handling-errors.md +++ b/docs/ko/docs/tutorial/handling-errors.md @@ -81,7 +81,7 @@ HTTP 오류에 커스텀 헤더를 추가할 수 있으면 유용한 상황이 ## 커스텀 예외 핸들러 설치하기 { #install-custom-exception-handlers } -Starlette의 동일한 예외 유틸리티를 사용해 커스텀 예외 핸들러를 추가할 수 있습니다. +[Starlette의 동일한 예외 유틸리티](https://www.starlette.dev/exceptions/)를 사용해 커스텀 예외 핸들러를 추가할 수 있습니다. 여러분(또는 사용하는 라이브러리)이 `raise`할 수 있는 커스텀 예외 `UnicornException`이 있다고 가정해 봅시다. diff --git a/docs/ko/docs/tutorial/index.md b/docs/ko/docs/tutorial/index.md index c44aac2d4d..7f8c374725 100644 --- a/docs/ko/docs/tutorial/index.md +++ b/docs/ko/docs/tutorial/index.md @@ -15,7 +15,7 @@
```console -$ fastapi dev main.py +$ fastapi dev FastAPI Starting development server 🚀 @@ -62,7 +62,7 @@ $ fastapi dev @@ -76,7 +76,7 @@ $ pip install "fastapi[standard]" /// note | 참고 -`pip install "fastapi[standard]"`로 설치하면 `fastapi-cloud-cli`를 포함한 몇 가지 기본 선택적 standard 의존성이 함께 설치되며, 이를 사용해 FastAPI Cloud에 배포할 수 있습니다. +`pip install "fastapi[standard]"`로 설치하면 `fastapi-cloud-cli`를 포함한 몇 가지 기본 선택적 standard 의존성이 함께 설치되며, 이를 사용해 [FastAPI Cloud](https://fastapicloud.com)에 배포할 수 있습니다. 이러한 선택적 의존성이 필요 없다면 `pip install fastapi`로 대신 설치할 수 있습니다. @@ -84,6 +84,12 @@ standard 의존성은 설치하되 `fastapi-cloud-cli` 없이 설치하려면 `p /// +/// tip | 팁 + +FastAPI는 VS Code(및 Cursor)용 [공식 확장 프로그램](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode)이 있습니다. 경로 처리 탐색기, 경로 처리 검색, 테스트에서의 CodeLens 탐색(테스트에서 정의로 바로 이동), FastAPI Cloud 배포와 로그 등 많은 기능을 에디터에서 바로 제공합니다. + +/// + ## 고급 사용자 안내서 { #advanced-user-guide } 이 **자습서 - 사용자 안내서**를 읽은 뒤에 나중에 읽을 수 있는 **고급 사용자 안내서**도 있습니다. diff --git a/docs/ko/docs/tutorial/metadata.md b/docs/ko/docs/tutorial/metadata.md index 2107ea90a7..9220dc2b47 100644 --- a/docs/ko/docs/tutorial/metadata.md +++ b/docs/ko/docs/tutorial/metadata.md @@ -14,7 +14,7 @@ OpenAPI 명세 및 자동화된 API 문서 UI에 사용되는 다음 필드를 | `version` | `string` | API의 버전입니다. OpenAPI의 버전이 아닌, 여러분의 애플리케이션의 버전을 나타냅니다. 예: `2.5.0`. | | `terms_of_service` | `str` | API 이용 약관의 URL입니다. 제공하는 경우 URL 형식이어야 합니다. | | `contact` | `dict` | 노출된 API에 대한 연락처 정보입니다. 여러 필드를 포함할 수 있습니다.
contact 필드
매개변수타입설명
namestr연락처 인물/조직의 식별명입니다.
urlstr연락처 정보가 담긴 URL입니다. URL 형식이어야 합니다.
emailstr연락처 인물/조직의 이메일 주소입니다. 이메일 주소 형식이어야 합니다.
| -| `license_info` | `dict` | 노출된 API의 라이선스 정보입니다. 여러 필드를 포함할 수 있습니다.
license_info 필드
매개변수타입설명
namestr필수 (license_info가 설정된 경우). API에 사용된 라이선스 이름입니다.
identifierstrAPI에 대한 SPDX 라이선스 표현입니다. identifier 필드는 url 필드와 상호 배타적입니다. OpenAPI 3.1.0, FastAPI 0.99.0부터 사용 가능.
urlstrAPI에 사용된 라이선스의 URL입니다. URL 형식이어야 합니다.
| +| `license_info` | `dict` | 노출된 API의 라이선스 정보입니다. 여러 필드를 포함할 수 있습니다.
license_info 필드
매개변수타입설명
namestr필수 (license_info가 설정된 경우). API에 사용된 라이선스 이름입니다.
identifierstrAPI에 대한 [SPDX](https://spdx.org/licenses/) 라이선스 표현입니다. identifier 필드는 url 필드와 상호 배타적입니다. OpenAPI 3.1.0, FastAPI 0.99.0부터 사용 가능.
urlstrAPI에 사용된 라이선스의 URL입니다. URL 형식이어야 합니다.
| 다음과 같이 설정할 수 있습니다: @@ -40,7 +40,7 @@ OpenAPI 3.1.0 및 FastAPI 0.99.0부터 `license_info`에 `url` 대신 `identifie ## 태그에 대한 메타데이터 { #metadata-for-tags } -`openapi_tags` 매개변수를 사용하여 경로 처리을 그룹화하는 데 사용되는 여러 태그에 추가 메타데이터를 추가할 수도 있습니다. +`openapi_tags` 매개변수를 사용하여 경로 처리를 그룹화하는 데 사용되는 여러 태그에 추가 메타데이터를 추가할 수도 있습니다. 리스트는 각 태그에 대해 하나의 딕셔너리를 포함합니다. @@ -76,7 +76,7 @@ OpenAPI 3.1.0 및 FastAPI 0.99.0부터 `license_info`에 `url` 대신 `identifie /// info | 정보 -태그에 대한 자세한 내용은 [경로 처리 구성](path-operation-configuration.md#tags){.internal-link target=_blank}에서 읽어보세요. +태그에 대한 자세한 내용은 [경로 처리 구성](path-operation-configuration.md#tags)에서 읽어보세요. /// diff --git a/docs/ko/docs/tutorial/middleware.md b/docs/ko/docs/tutorial/middleware.md index 6c4f33fd98..b459f6434e 100644 --- a/docs/ko/docs/tutorial/middleware.md +++ b/docs/ko/docs/tutorial/middleware.md @@ -1,10 +1,10 @@ # 미들웨어 { #middleware } -미들웨어를 **FastAPI** 응용 프로그램에 추가할 수 있습니다. +미들웨어를 **FastAPI** 애플리케이션에 추가할 수 있습니다. "미들웨어"는 특정 *경로 처리*에 의해 처리되기 전, 모든 **요청**에 대해서 동작하는 함수입니다. 또한 모든 **응답**이 반환되기 전에도 동일하게 동작합니다. -* 미들웨어는 응용 프로그램으로 오는 각 **요청**을 가져옵니다. +* 미들웨어는 애플리케이션으로 오는 각 **요청**을 가져옵니다. * 그런 다음 해당 **요청**에 대해 무언가를 하거나 필요한 코드를 실행할 수 있습니다. * 그런 다음 **요청**을 나머지 애플리케이션(어떤 *경로 처리*가)을 통해 처리되도록 전달합니다. * 그런 다음 애플리케이션(어떤 *경로 처리*가)이 생성한 **응답**을 가져옵니다. @@ -15,7 +15,7 @@ `yield`를 사용하는 의존성이 있다면, exit 코드는 미들웨어 *후에* 실행됩니다. -백그라운드 작업(뒤에서 보게 될 [백그라운드 작업](background-tasks.md){.internal-link target=_blank} 섹션에서 다룹니다)이 있다면, 모든 미들웨어 *후에* 실행됩니다. +백그라운드 작업(뒤에서 보게 될 [백그라운드 작업](background-tasks.md) 섹션에서 다룹니다)이 있다면, 모든 미들웨어 *후에* 실행됩니다. /// @@ -35,9 +35,9 @@ /// tip | 팁 -사용자 정의 독점 헤더는 `X-` 접두사를 사용하여 추가할 수 있다는 점을 기억하세요. +사용자 정의 독점 헤더는 [`X-` 접두사를 사용](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)하여 추가할 수 있다는 점을 기억하세요. -하지만 브라우저에서 클라이언트가 볼 수 있게 하려는 사용자 정의 헤더가 있다면, Starlette의 CORS 문서에 문서화된 `expose_headers` 매개변수를 사용해 CORS 설정([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank})에 추가해야 합니다. +하지만 브라우저에서 클라이언트가 볼 수 있게 하려는 사용자 정의 헤더가 있다면, [CORS (Cross-Origin Resource Sharing)](cors.md) 설정에 [Starlette의 CORS 문서](https://www.starlette.dev/middleware/#corsmiddleware)에 문서화된 `expose_headers` 매개변수를 사용해 추가해야 합니다. /// @@ -61,7 +61,7 @@ /// tip | 팁 -여기서는 이러한 사용 사례에서 더 정확할 수 있기 때문에 `time.time()` 대신 `time.perf_counter()`를 사용합니다. 🤓 +여기서는 이러한 사용 사례에서 더 정확할 수 있기 때문에 `time.time()` 대신 [`time.perf_counter()`](https://docs.python.org/3/library/time.html#time.perf_counter)를 사용합니다. 🤓 /// @@ -90,6 +90,6 @@ app.add_middleware(MiddlewareB) ## 다른 미들웨어 { #other-middlewares } -다른 미들웨어에 대한 더 많은 정보는 나중에 [숙련된 사용자 안내서: 향상된 미들웨어](../advanced/middleware.md){.internal-link target=_blank}에서 확인할 수 있습니다. +다른 미들웨어에 대한 더 많은 정보는 나중에 [숙련된 사용자 안내서: 향상된 미들웨어](../advanced/middleware.md)에서 확인할 수 있습니다. 다음 섹션에서 미들웨어로 CORS를 처리하는 방법을 보게 될 것입니다. diff --git a/docs/ko/docs/tutorial/path-operation-configuration.md b/docs/ko/docs/tutorial/path-operation-configuration.md index 0d6a0d4229..ebdf6f918f 100644 --- a/docs/ko/docs/tutorial/path-operation-configuration.md +++ b/docs/ko/docs/tutorial/path-operation-configuration.md @@ -58,7 +58,7 @@ 설명은 보통 길어지고 여러 줄에 걸쳐있기 때문에, *경로 처리* 설명을 함수 독스트링에 선언할 수 있으며, **FastAPI**는 그곳에서 이를 읽습니다. -독스트링에는 Markdown을 작성할 수 있으며, (독스트링의 들여쓰기를 고려하여) 올바르게 해석되고 표시됩니다. +독스트링에는 [Markdown](https://en.wikipedia.org/wiki/Markdown)을 작성할 수 있으며, (독스트링의 들여쓰기를 고려하여) 올바르게 해석되고 표시됩니다. {* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *} diff --git a/docs/ko/docs/tutorial/path-params-numeric-validations.md b/docs/ko/docs/tutorial/path-params-numeric-validations.md index 51f9fe2c14..2ff56c46e7 100644 --- a/docs/ko/docs/tutorial/path-params-numeric-validations.md +++ b/docs/ko/docs/tutorial/path-params-numeric-validations.md @@ -14,7 +14,7 @@ FastAPI는 0.95.0 버전에서 `Annotated` 지원을 추가했고(그리고 이 더 오래된 버전이 있다면 `Annotated`를 사용하려고 할 때 오류가 발생합니다. -`Annotated`를 사용하기 전에 최소 0.95.1까지 [FastAPI 버전 업그레이드](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}를 꼭 하세요. +`Annotated`를 사용하기 전에 최소 0.95.1까지 [FastAPI 버전 업그레이드](../deployment/versions.md#upgrading-the-fastapi-versions)를 꼭 하세요. /// @@ -81,7 +81,7 @@ FastAPI는 0.95.0 버전에서 `Annotated` 지원을 추가했고(그리고 이 함수의 첫 번째 매개변수로 `*`를 전달하세요. -파이썬은 `*`으로 아무것도 하지 않지만, 뒤따르는 모든 매개변수는 키워드 인자(키-값 쌍)로 호출되어야 함을 알게 됩니다. 이는 kwargs로도 알려져 있습니다. 기본값이 없더라도 마찬가지입니다. +파이썬은 `*`으로 아무것도 하지 않지만, 뒤따르는 모든 매개변수는 키워드 인자(키-값 쌍)로 호출되어야 함을 알게 됩니다. 이는 kwargs로도 알려져 있습니다. 기본값이 없더라도 마찬가지입니다. {* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} @@ -112,17 +112,17 @@ FastAPI는 0.95.0 버전에서 `Annotated` 지원을 추가했고(그리고 이 숫자 검증은 `float` 값에도 동작합니다. -여기에서 gt를, ge뿐만 아니라 선언할 수 있다는 점이 중요해집니다. 예를 들어 값이 `1`보다 작더라도, 반드시 `0`보다 커야 한다고 요구할 수 있습니다. +여기에서 gt를, ge뿐만 아니라 선언할 수 있다는 점이 중요해집니다. 예를 들어 값이 `1`보다 작더라도, 반드시 `0`보다 커야 한다고 요구할 수 있습니다. 즉, `0.5`는 유효한 값입니다. 그러나 `0.0` 또는 `0`은 그렇지 않습니다. -lt 역시 마찬가지입니다. +lt 역시 마찬가지입니다. {* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} ## 요약 { #recap } -`Query`, `Path`(아직 보지 못한 다른 것들도)를 사용하면 [쿼리 매개변수와 문자열 검증](query-params-str-validations.md){.internal-link target=_blank}에서와 마찬가지로 메타데이터와 문자열 검증을 선언할 수 있습니다. +`Query`, `Path`(아직 보지 못한 다른 것들도)를 사용하면 [쿼리 매개변수와 문자열 검증](query-params-str-validations.md)에서와 마찬가지로 메타데이터와 문자열 검증을 선언할 수 있습니다. 그리고 숫자 검증 또한 선언할 수 있습니다: diff --git a/docs/ko/docs/tutorial/path-params.md b/docs/ko/docs/tutorial/path-params.md index c6e973709a..c6ea6b7c16 100644 --- a/docs/ko/docs/tutorial/path-params.md +++ b/docs/ko/docs/tutorial/path-params.md @@ -6,7 +6,7 @@ 경로 매개변수 `item_id`의 값은 함수의 `item_id` 인자로 전달됩니다. -그래서 이 예제를 실행하고 http://127.0.0.1:8000/items/foo로 이동하면, 다음 응답을 볼 수 있습니다: +그래서 이 예제를 실행하고 [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/items/foo)로 이동하면, 다음 응답을 볼 수 있습니다: ```JSON {"item_id":"foo"} @@ -28,7 +28,7 @@ ## 데이터 변환 { #data-conversion } -이 예제를 실행하고 http://127.0.0.1:8000/items/3을 열면, 다음 응답을 볼 수 있습니다: +이 예제를 실행하고 [http://127.0.0.1:8000/items/3](http://127.0.0.1:8000/items/3)을 열면, 다음 응답을 볼 수 있습니다: ```JSON {"item_id":3} @@ -44,7 +44,7 @@ ## 데이터 검증 { #data-validation } -하지만 브라우저에서 http://127.0.0.1:8000/items/foo로 이동하면, 다음과 같은 HTTP 오류를 볼 수 있습니다: +하지만 브라우저에서 [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/items/foo)로 이동하면, 다음과 같은 HTTP 오류를 볼 수 있습니다: ```JSON { @@ -64,7 +64,7 @@ 경로 매개변수 `item_id`가 `int`가 아닌 `"foo"` 값을 가졌기 때문입니다. -`int` 대신 `float`을 제공하면(예: http://127.0.0.1:8000/items/4.2) 동일한 오류가 나타납니다. +`int` 대신 `float`을 제공하면(예: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2)) 동일한 오류가 나타납니다. /// check | 확인 @@ -78,7 +78,7 @@ ## 문서화 { #documentation } -그리고 브라우저에서 http://127.0.0.1:8000/docs를 열면, 다음과 같이 자동 대화식 API 문서를 볼 수 있습니다: +그리고 브라우저에서 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)를 열면, 다음과 같이 자동 대화식 API 문서를 볼 수 있습니다: @@ -92,9 +92,9 @@ ## 표준 기반의 이점, 대체 문서 { #standards-based-benefits-alternative-documentation } -그리고 생성된 스키마는 OpenAPI 표준에서 나온 것이기 때문에 호환되는 도구가 많이 있습니다. +그리고 생성된 스키마는 [OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md) 표준에서 나온 것이기 때문에 호환되는 도구가 많이 있습니다. -이 덕분에 **FastAPI** 자체에서 http://127.0.0.1:8000/redoc로 접속할 수 있는 (ReDoc을 사용하는) 대체 API 문서를 제공합니다: +이 덕분에 **FastAPI** 자체에서 [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)로 접속할 수 있는 (ReDoc을 사용하는) 대체 API 문서를 제공합니다: @@ -102,7 +102,7 @@ ## Pydantic { #pydantic } -모든 데이터 검증은 Pydantic에 의해 내부적으로 수행되므로 이로 인한 이점을 모두 얻을 수 있습니다. 여러분은 관리를 잘 받고 있음을 느낄 수 있습니다. +모든 데이터 검증은 [Pydantic](https://docs.pydantic.dev/)에 의해 내부적으로 수행되므로 이로 인한 이점을 모두 얻을 수 있습니다. 여러분은 관리를 잘 받고 있음을 느낄 수 있습니다. `str`, `float`, `bool`, 그리고 다른 여러 복잡한 데이터 타입 선언을 할 수 있습니다. @@ -130,7 +130,7 @@ ## 사전정의 값 { #predefined-values } -만약 *경로 매개변수*를 받는 *경로 처리*가 있지만, 가능한 유효한 *경로 매개변수* 값들을 미리 정의하고 싶다면 파이썬 표준 `Enum`을 사용할 수 있습니다. +만약 *경로 매개변수*를 받는 *경로 처리*가 있지만, 가능한 유효한 *경로 매개변수* 값들을 미리 정의하고 싶다면 파이썬 표준 `Enum`을 사용할 수 있습니다. ### `Enum` 클래스 생성 { #create-an-enum-class } @@ -150,7 +150,7 @@ ### *경로 매개변수* 선언 { #declare-a-path-parameter } -생성한 열거형 클래스(`ModelName`)를 사용하는 타입 어노테이션으로 *경로 매개변수*를 만듭니다: +생성한 열거형 클래스(`ModelName`)를 사용하는 타입 어노테이션으로 *경로 매개변수를* 만듭니다: {* ../../docs_src/path_params/tutorial005_py310.py hl[16] *} diff --git a/docs/ko/docs/tutorial/query-params-str-validations.md b/docs/ko/docs/tutorial/query-params-str-validations.md index 2b608fd1d5..d4acff151d 100644 --- a/docs/ko/docs/tutorial/query-params-str-validations.md +++ b/docs/ko/docs/tutorial/query-params-str-validations.md @@ -35,13 +35,13 @@ FastAPI는 0.95.0 버전에서 `Annotated` 지원을 추가했고(그리고 이 이전 버전을 사용하면 `Annotated`를 사용하려고 할 때 오류가 발생합니다. -`Annotated`를 사용하기 전에 최소 0.95.1 버전으로 [FastAPI 버전 업그레이드](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}를 진행하세요. +`Annotated`를 사용하기 전에 최소 0.95.1 버전으로 [FastAPI 버전 업그레이드](../deployment/versions.md#upgrading-the-fastapi-versions)를 진행하세요. /// ## `q` 매개변수의 타입에 `Annotated` 사용하기 { #use-annotated-in-the-type-for-the-q-parameter } -이전에 [Python 타입 소개](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}에서 `Annotated`를 사용해 매개변수에 메타데이터를 추가할 수 있다고 말씀드린 것을 기억하시나요? +이전에 [Python 타입 소개](../python-types.md#type-hints-with-metadata-annotations)에서 `Annotated`를 사용해 매개변수에 메타데이터를 추가할 수 있다고 말씀드린 것을 기억하시나요? 이제 FastAPI에서 사용할 차례입니다. 🚀 @@ -158,7 +158,7 @@ FastAPI 없이도 **다른 곳에서** 같은 함수를 **호출**할 수 있고 `Annotated`를 사용하지 않고 **(이전) 기본값 스타일**을 사용하면, FastAPI 없이 **다른 곳에서** 함수를 호출할 때도 제대로 동작하도록 함수에 인자를 전달해야 한다는 것을 **기억**해야 합니다. 그렇지 않으면 값이 기대와 다르게 됩니다(예: `str` 대신 `QueryInfo` 같은 것). 그리고 편집기도 경고하지 않고 Python도 그 함수를 실행할 때는 불평하지 않으며, 오직 내부 동작에서 오류가 발생할 때만 문제가 드러납니다. -`Annotated`는 하나 이상의 메타데이터 어노테이션을 가질 수 있기 때문에, 이제 Typer 같은 다른 도구에서도 같은 함수를 사용할 수 있습니다. 🚀 +`Annotated`는 하나 이상의 메타데이터 어노테이션을 가질 수 있기 때문에, 이제 [Typer](https://typer.tiangolo.com/) 같은 다른 도구에서도 같은 함수를 사용할 수 있습니다. 🚀 ## 검증 더 추가하기 { #add-more-validations } @@ -370,11 +370,11 @@ http://127.0.0.1:8000/items/?item-query=foobaritems 그런 경우에는 일반적인 검증(예: 값이 `str`인지 검증한 뒤) 이후에 적용되는 **커스텀 검증 함수**를 사용할 수 있습니다. -`Annotated` 안에서 Pydantic의 `AfterValidator`를 사용하면 이를 구현할 수 있습니다. +`Annotated` 안에서 [Pydantic의 `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator)를 사용하면 이를 구현할 수 있습니다. /// tip | 팁 -Pydantic에는 `BeforeValidator`와 같은 다른 것들도 있습니다. 🤓 +Pydantic에는 [BeforeValidator](https://docs.pydantic.dev/latest/concepts/validators/#field-before-validator)와 같은 다른 것들도 있습니다. 🤓 /// diff --git a/docs/ko/docs/tutorial/query-params.md b/docs/ko/docs/tutorial/query-params.md index 0a6b1f922c..4dffc90570 100644 --- a/docs/ko/docs/tutorial/query-params.md +++ b/docs/ko/docs/tutorial/query-params.md @@ -183,6 +183,6 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy /// tip -[경로 매개변수](path-params.md#predefined-values){.internal-link target=_blank}와 마찬가지로 `Enum`을 사용할 수 있습니다. +[경로 매개변수](path-params.md#predefined-values)와 마찬가지로 `Enum`을 사용할 수 있습니다. /// diff --git a/docs/ko/docs/tutorial/request-files.md b/docs/ko/docs/tutorial/request-files.md index 3ee0fa74c3..49522ac252 100644 --- a/docs/ko/docs/tutorial/request-files.md +++ b/docs/ko/docs/tutorial/request-files.md @@ -4,9 +4,9 @@ /// info | 정보 -업로드된 파일을 전달받기 위해 먼저 `python-multipart`를 설치해야합니다. +업로드된 파일을 전달받기 위해 먼저 [`python-multipart`](https://github.com/Kludex/python-multipart)를 설치해야합니다. -[가상 환경](../virtual-environments.md){.internal-link target=_blank}을 생성하고, 활성화한 다음, 예를 들어 다음과 같이 설치하세요: +[가상 환경](../virtual-environments.md)을 생성하고, 활성화한 다음, 예를 들어 다음과 같이 설치하세요: ```console $ pip install python-multipart @@ -63,8 +63,8 @@ File의 본문을 선언할 때, 매개변수가 쿼리 매개변수 또는 본 * 최대 크기 제한까지만 메모리에 저장되며, 이를 초과하는 경우 디스크에 저장됩니다. * 따라서 이미지, 동영상, 큰 이진코드와 같은 대용량 파일들을 많은 메모리를 소모하지 않고 처리하기에 적합합니다. * 업로드 된 파일의 메타데이터를 얻을 수 있습니다. -* file-like `async` 인터페이스를 갖고 있습니다. -* file-like object를 필요로하는 다른 라이브러리에 직접적으로 전달할 수 있는 파이썬 `SpooledTemporaryFile` 객체를 반환합니다. +* [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) `async` 인터페이스를 갖고 있습니다. +* file-like object를 필요로하는 다른 라이브러리에 직접적으로 전달할 수 있는 파이썬 [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) 객체를 반환합니다. ### `UploadFile` { #uploadfile } @@ -72,7 +72,7 @@ File의 본문을 선언할 때, 매개변수가 쿼리 매개변수 또는 본 * `filename` : 문자열(`str`)로 된 업로드된 파일의 파일명입니다 (예: `myimage.jpg`). * `content_type` : 문자열(`str`)로 된 파일 형식(MIME type / media type)입니다 (예: `image/jpeg`). -* `file` : `SpooledTemporaryFile` (a file-like object)입니다. 이것은 "file-like" 객체를 필요로하는 다른 함수나 라이브러리에 직접적으로 전달할 수 있는 실질적인 파이썬 파일 객체입니다. +* `file` : [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) (a [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) object)입니다. 이것은 "file-like" 객체를 필요로하는 다른 함수나 라이브러리에 직접적으로 전달할 수 있는 실질적인 파이썬 파일 객체입니다. `UploadFile` 에는 다음의 `async` 메소드들이 있습니다. 이들은 내부적인 `SpooledTemporaryFile` 을 사용하여 해당하는 파일 메소드를 호출합니다. @@ -121,7 +121,7 @@ HTML의 폼들(`
`)이 서버에 데이터를 전송하는 방식은 하지만 파일이 포함된 경우, `multipart/form-data`로 인코딩됩니다. `File`을 사용하였다면, **FastAPI**는 본문의 적합한 부분에서 파일을 가져와야 한다는 것을 인지합니다. -인코딩과 폼 필드에 대해 더 알고싶다면, MDN web docs for POST를 참고하기 바랍니다. +인코딩과 폼 필드에 대해 더 알고싶다면, [MDN 웹 문서의 `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)를 참고하기 바랍니다. /// diff --git a/docs/ko/docs/tutorial/request-form-models.md b/docs/ko/docs/tutorial/request-form-models.md index 20a2e95972..4a5c3e1a75 100644 --- a/docs/ko/docs/tutorial/request-form-models.md +++ b/docs/ko/docs/tutorial/request-form-models.md @@ -4,9 +4,9 @@ FastAPI에서 **Pydantic 모델**을 이용하여 **폼 필드**를 선언할 /// info | 정보 -폼을 사용하려면, 먼저 `python-multipart`를 설치하세요. +폼을 사용하려면, 먼저 [`python-multipart`](https://github.com/Kludex/python-multipart)를 설치하세요. -[가상 환경](../virtual-environments.md){.internal-link target=_blank}을 생성하고 활성화한 다음, 예를 들어 아래와 같이 설치하세요: +[가상 환경](../virtual-environments.md)을 생성하고 활성화한 다음, 예를 들어 아래와 같이 설치하세요: ```console $ pip install python-multipart diff --git a/docs/ko/docs/tutorial/request-forms-and-files.md b/docs/ko/docs/tutorial/request-forms-and-files.md index 4c2d12bc06..fa8fdae7e8 100644 --- a/docs/ko/docs/tutorial/request-forms-and-files.md +++ b/docs/ko/docs/tutorial/request-forms-and-files.md @@ -2,11 +2,11 @@ `File` 과 `Form` 을 사용하여 파일과 폼 필드를 동시에 정의할 수 있습니다. -/// info | 정보 +/// info -업로드된 파일 및/또는 폼 데이터를 받으려면 먼저 `python-multipart`를 설치해야 합니다. +업로드된 파일 및/또는 폼 데이터를 받으려면 먼저 [`python-multipart`](https://github.com/Kludex/python-multipart)를 설치해야 합니다. -[가상 환경](../virtual-environments.md){.internal-link target=_blank}을 생성하고, 활성화한 다음 설치해야 합니다. 예: +[가상 환경](../virtual-environments.md)을 생성하고, 활성화한 다음 설치해야 합니다. 예: ```console $ pip install python-multipart @@ -28,7 +28,7 @@ $ pip install python-multipart 또한 일부 파일은 `bytes`로, 일부 파일은 `UploadFile`로 선언할 수 있습니다. -/// warning | 경고 +/// warning 다수의 `File`과 `Form` 매개변수를 한 *경로 처리*에 선언하는 것이 가능하지만, 요청의 본문이 `application/json`가 아닌 `multipart/form-data`로 인코딩되기 때문에 JSON으로 받기를 기대하는 `Body` 필드를 함께 선언할 수는 없습니다. diff --git a/docs/ko/docs/tutorial/request-forms.md b/docs/ko/docs/tutorial/request-forms.md index a830bc5f8a..4a618f5873 100644 --- a/docs/ko/docs/tutorial/request-forms.md +++ b/docs/ko/docs/tutorial/request-forms.md @@ -4,9 +4,9 @@ JSON 대신 폼 필드를 받아야 하는 경우 `Form`을 사용할 수 있습 /// info | 정보 -폼을 사용하려면, 먼저 `python-multipart`를 설치하세요. +폼을 사용하려면, 먼저 [`python-multipart`](https://github.com/Kludex/python-multipart)를 설치하세요. -[가상 환경](../virtual-environments.md){.internal-link target=_blank}을 생성하고 활성화한 다음, 아래와 같이 설치할 수 있습니다: +[가상 환경](../virtual-environments.md)을 생성하고 활성화한 다음, 예를 들어 다음과 같이 설치하세요: ```console $ pip install python-multipart @@ -40,7 +40,7 @@ $ pip install python-multipart /// tip | 팁 -폼 본문을 선언할 때, 폼이 없으면 매개변수가 쿼리 매개변수나 본문(JSON) 매개변수로 해석(interpret)되기 때문에 `Form`을 명시적으로 사용해야 합니다. +폼 본문을 선언할 때는 `Form`을 명시적으로 사용해야 합니다. 그렇지 않으면 매개변수가 쿼리 매개변수나 본문(JSON) 매개변수로 해석됩니다. /// @@ -56,7 +56,7 @@ HTML 폼(`
`)이 데이터를 서버로 보내는 방식은 일반 그러나 폼에 파일이 포함된 경우, `multipart/form-data`로 인코딩합니다. 다음 장에서 파일 처리에 대해 읽을 겁니다. -이러한 인코딩 및 폼 필드에 대해 더 읽고 싶다면, MDN 웹 문서를 참조하세요 POST에 대한. +이러한 인코딩 및 폼 필드에 대해 더 읽고 싶다면, [`POST`에 대한 MDN 웹 문서를 참조하세요](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// diff --git a/docs/ko/docs/tutorial/response-model.md b/docs/ko/docs/tutorial/response-model.md index 942901e7cc..f3d1046267 100644 --- a/docs/ko/docs/tutorial/response-model.md +++ b/docs/ko/docs/tutorial/response-model.md @@ -13,6 +13,7 @@ FastAPI는 이 반환 타입을 사용하여: * OpenAPI *경로 처리*의 응답에 **JSON Schema**를 추가합니다. * 이는 **자동 문서**에서 사용됩니다. * 또한 자동 클라이언트 코드 생성 도구에서도 사용됩니다. +* 반환된 데이터를 Pydantic을 사용해 JSON으로 **직렬화**합니다. Pydantic은 **Rust**로 작성되어 있어 **훨씬 더 빠릅니다**. 하지만 가장 중요한 것은: @@ -73,9 +74,9 @@ FastAPI는 이 `response_model`을 사용해 데이터 문서화, 검증 등을 /// info | 정보 -`EmailStr`을 사용하려면 먼저 `email-validator`를 설치하세요. +`EmailStr`을 사용하려면 먼저 [`email-validator`](https://github.com/JoshData/python-email-validator)를 설치하세요. -[가상 환경](../virtual-environments.md){.internal-link target=_blank}을 생성하고, 활성화한 다음 설치해야 합니다. 예를 들어: +[가상 환경](../virtual-environments.md)을 생성하고, 활성화한 다음 설치해야 합니다. 예를 들어: ```console $ pip install email-validator @@ -181,7 +182,7 @@ FastAPI는 Pydantic을 내부적으로 여러 방식으로 사용하여, 클래 ### 응답을 직접 반환하기 { #return-a-response-directly } -가장 흔한 경우는 [고급 문서에서 나중에 설명하는 대로 Response를 직접 반환하는 것](../advanced/response-directly.md){.internal-link target=_blank}입니다. +가장 흔한 경우는 [고급 문서에서 나중에 설명하는 대로 Response를 직접 반환하는 것](../advanced/response-directly.md)입니다. {* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} @@ -257,7 +258,7 @@ FastAPI는 Pydantic을 내부적으로 여러 방식으로 사용하여, 클래 * `response_model_exclude_defaults=True` * `response_model_exclude_none=True` -`exclude_defaults` 및 `exclude_none`에 대해 Pydantic 문서에 설명된 대로 사용할 수 있습니다. +`exclude_defaults` 및 `exclude_none`에 대해 [Pydantic 문서](https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict)에 설명된 대로 사용할 수 있습니다. /// diff --git a/docs/ko/docs/tutorial/response-status-code.md b/docs/ko/docs/tutorial/response-status-code.md index c81132dfb9..68db66e338 100644 --- a/docs/ko/docs/tutorial/response-status-code.md +++ b/docs/ko/docs/tutorial/response-status-code.md @@ -20,7 +20,7 @@ /// info | 정보 -`status_code` 는 파이썬의 `http.HTTPStatus` 와 같은 `IntEnum` 을 입력받을 수도 있습니다. +`status_code` 는 파이썬의 [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus) 와 같은 `IntEnum` 을 입력받을 수도 있습니다. /// @@ -43,7 +43,7 @@ FastAPI는 이를 알고 있으며, 응답 본문이 없다고 명시하는 Open /// note | 참고 -만약 HTTP 상태 코드가 무엇인지 이미 알고 있다면, 다음 섡션으로 넘어가세요. +만약 HTTP 상태 코드가 무엇인지 이미 알고 있다면, 다음 섹션으로 넘어가세요. /// @@ -66,7 +66,7 @@ HTTP에서는 응답의 일부로 3자리 숫자 상태 코드를 보냅니다. /// tip | 팁 -각 상태 코드와 어떤 코드가 어떤 용도인지 더 알고 싶다면 MDN의 HTTP 상태 코드에 관한 문서를 확인하세요. +각 상태 코드와 어떤 코드가 어떤 용도인지 더 알고 싶다면 [MDN의 HTTP 상태 코드에 관한 문서](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)를 확인하세요. /// @@ -98,4 +98,4 @@ HTTP에서는 응답의 일부로 3자리 숫자 상태 코드를 보냅니다. ## 기본값 변경 { #changing-the-default } -나중에 [고급 사용자 지침서](../advanced/response-change-status-code.md){.internal-link target=_blank}에서, 여기서 선언하는 기본값과 다른 상태 코드를 반환하는 방법을 확인할 수 있습니다. +나중에 [고급 사용자 지침서](../advanced/response-change-status-code.md)에서, 여기서 선언하는 기본값과 다른 상태 코드를 반환하는 방법을 확인할 수 있습니다. diff --git a/docs/ko/docs/tutorial/schema-extra-example.md b/docs/ko/docs/tutorial/schema-extra-example.md index a1d0c84689..ffa97375df 100644 --- a/docs/ko/docs/tutorial/schema-extra-example.md +++ b/docs/ko/docs/tutorial/schema-extra-example.md @@ -2,7 +2,7 @@ 여러분의 앱이 받을 수 있는 데이터 예제를 선언할 수 있습니다. -여기 이를 위한 몇가지 방식이 있습니다. +여기 이를 위한 몇 가지 방식이 있습니다. ## Pydantic 모델 속 추가 JSON 스키마 데이터 { #extra-json-schema-data-in-pydantic-models } @@ -12,7 +12,7 @@ 추가 정보는 있는 그대로 해당 모델의 **JSON 스키마** 결과에 추가되고, API 문서에서 사용합니다. -Pydantic 문서: Configuration에 설명된 것처럼 `dict`를 받는 `model_config` 어트리뷰트를 사용할 수 있습니다. +[Pydantic 문서: Configuration](https://docs.pydantic.dev/latest/api/config/)에 설명된 것처럼 `dict`를 받는 `model_config` 어트리뷰트를 사용할 수 있습니다. `"json_schema_extra"`를 생성된 JSON 스키마에서 보여주고 싶은 별도의 데이터와 `examples`를 포함하는 `dict`으로 설정할 수 있습니다. @@ -145,12 +145,12 @@ JSON 스키마는 `examples`를 가지고 있지 않았고, 따라서 OpenAPI는 OpenAPI는 또한 `example`과 `examples` 필드를 명세서의 다른 부분에 추가했습니다: -* `Parameter Object` (명세서에 있는)는 FastAPI의 다음 기능에서 쓰였습니다: +* [`Parameter Object` (명세서에 있는)](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-object)는 FastAPI의 다음 기능에서 쓰였습니다: * `Path()` * `Query()` * `Header()` * `Cookie()` -* `Request Body Object`, `Media Type Object` (명세서에 있는)의 `content` 필드에 있는는 FastAPI의 다음 기능에서 쓰였습니다: +* [`Request Body Object`, `Media Type Object` (명세서에 있는)의 `content` 필드에 있는](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#media-type-object)는 FastAPI의 다음 기능에서 쓰였습니다: * `Body()` * `File()` * `Form()` @@ -163,7 +163,7 @@ OpenAPI는 또한 `example`과 `examples` 필드를 명세서의 다른 부분 ### JSON 스키마의 `examples` 필드 { #json-schemas-examples-field } -하지만, 후에 JSON 스키마는 `examples` 필드를 명세서의 새 버전에 추가했습니다. +하지만, 후에 JSON 스키마는 [`examples`](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5) 필드를 명세서의 새 버전에 추가했습니다. 그리고 새로운 OpenAPI 3.1.0은 이 새로운 `examples` 필드가 포함된 최신 버전 (JSON 스키마 2020-12)을 기반으로 했습니다. diff --git a/docs/ko/docs/tutorial/security/first-steps.md b/docs/ko/docs/tutorial/security/first-steps.md index 57b336d52d..8b7563ec3e 100644 --- a/docs/ko/docs/tutorial/security/first-steps.md +++ b/docs/ko/docs/tutorial/security/first-steps.md @@ -26,11 +26,11 @@ /// info | 정보 -`python-multipart` 패키지는 `pip install "fastapi[standard]"` 명령을 실행하면 **FastAPI**와 함께 자동으로 설치됩니다. +[`python-multipart`](https://github.com/Kludex/python-multipart) 패키지는 `pip install "fastapi[standard]"` 명령을 실행하면 **FastAPI**와 함께 자동으로 설치됩니다. 하지만 `pip install fastapi` 명령을 사용하면 `python-multipart` 패키지가 기본으로 포함되지 않습니다. -수동으로 설치하려면, [가상 환경](../../virtual-environments.md){.internal-link target=_blank}을 만들고 활성화한 다음, 아래로 설치하세요: +수동으로 설치하려면, [가상 환경](../../virtual-environments.md)을 만들고 활성화한 다음, 아래로 설치하세요: ```console $ pip install python-multipart @@ -45,7 +45,7 @@ $ pip install python-multipart
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -54,7 +54,7 @@ $ fastapi dev main.py ## 확인하기 { #check-it } -대화형 문서로 이동하세요: http://127.0.0.1:8000/docs. +대화형 문서로 이동하세요: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). 다음과 비슷한 화면이 보일 것입니다: @@ -140,7 +140,7 @@ OAuth2는 backend 또는 API가 사용자를 인증하는 서버와 독립적일 상대 URL을 사용하므로, 예를 들어 API가 `https://example.com/`에 있다면 `https://example.com/token`을 가리킵니다. 하지만 API가 `https://example.com/api/v1/`에 있다면 `https://example.com/api/v1/token`을 가리킵니다. -상대 URL을 사용하는 것은 [프록시 뒤에서](../../advanced/behind-a-proxy.md){.internal-link target=_blank} 같은 고급 사용 사례에서도 애플리케이션이 계속 동작하도록 보장하는 데 중요합니다. +상대 URL을 사용하는 것은 [프록시 뒤에서](../../advanced/behind-a-proxy.md) 같은 고급 사용 사례에서도 애플리케이션이 계속 동작하도록 보장하는 데 중요합니다. /// diff --git a/docs/ko/docs/tutorial/security/oauth2-jwt.md b/docs/ko/docs/tutorial/security/oauth2-jwt.md index f9c4cc2ff3..3c3b93e3a6 100644 --- a/docs/ko/docs/tutorial/security/oauth2-jwt.md +++ b/docs/ko/docs/tutorial/security/oauth2-jwt.md @@ -24,13 +24,13 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4 1주일 뒤에는 토큰이 만료되고 사용자는 인가되지 않으므로 새 토큰을 받기 위해 다시 로그인해야 합니다. 그리고 사용자(또는 제3자)가 만료 시간을 바꾸기 위해 토큰을 수정하려고 하면, 서명이 일치하지 않기 때문에 이를 알아챌 수 있습니다. -JWT 토큰을 직접 다뤄보고 동작 방식을 확인해보고 싶다면 https://jwt.io를 확인하십시오. +JWT 토큰을 직접 다뤄보고 동작 방식을 확인해보고 싶다면 [https://jwt.io](https://jwt.io/)를 확인하십시오. ## `PyJWT` 설치 { #install-pyjwt } Python에서 JWT 토큰을 생성하고 검증하려면 `PyJWT`를 설치해야 합니다. -[가상환경](../../virtual-environments.md){.internal-link target=_blank}을 만들고 활성화한 다음 `pyjwt`를 설치하십시오: +[가상환경](../../virtual-environments.md)을 만들고 활성화한 다음 `pyjwt`를 설치하십시오:
@@ -46,7 +46,7 @@ $ pip install pyjwt RSA나 ECDSA 같은 전자 서명 알고리즘을 사용할 계획이라면, cryptography 라이브러리 의존성인 `pyjwt[crypto]`를 설치해야 합니다. -자세한 내용은 PyJWT Installation docs에서 확인할 수 있습니다. +자세한 내용은 [PyJWT 설치 문서](https://pyjwt.readthedocs.io/en/latest/installation.html)에서 확인할 수 있습니다. /// @@ -72,7 +72,7 @@ pwdlib는 패스워드 해시를 다루기 위한 훌륭한 Python 패키지입 추천 알고리즘은 "Argon2"입니다. -[가상환경](../../virtual-environments.md){.internal-link target=_blank}을 만들고 활성화한 다음 Argon2와 함께 pwdlib를 설치하십시오: +[가상환경](../../virtual-environments.md)을 만들고 활성화한 다음 Argon2와 함께 pwdlib를 설치하십시오:
@@ -200,7 +200,7 @@ JWT는 사용자를 식별하고 사용자가 API에서 직접 작업을 수행 ## 확인하기 { #check-it } -서버를 실행하고 문서로 이동하십시오: http://127.0.0.1:8000/docs. +서버를 실행하고 문서로 이동하십시오: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). 다음과 같은 사용자 인터페이스가 보일 것입니다: diff --git a/docs/ko/docs/tutorial/security/simple-oauth2.md b/docs/ko/docs/tutorial/security/simple-oauth2.md index 918c94b25f..48361de83d 100644 --- a/docs/ko/docs/tutorial/security/simple-oauth2.md +++ b/docs/ko/docs/tutorial/security/simple-oauth2.md @@ -146,7 +146,7 @@ UserInDB( /// info | 정보 -`**user_dict`에 대한 자세한 설명은 [**추가 모델** 문서](../extra-models.md#about-user-in-dict){.internal-link target=_blank}를 다시 확인해보세요. +`**user_dict`에 대한 자세한 설명은 [**추가 모델** 문서](../extra-models.md#about-user-in-dict)를 다시 확인해보세요. /// @@ -216,7 +216,7 @@ UserInDB( ## 확인하기 { #see-it-in-action } -대화형 문서 열기: http://127.0.0.1:8000/docs. +대화형 문서 열기: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). ### 인증하기 { #authenticate } diff --git a/docs/ko/docs/tutorial/sql-databases.md b/docs/ko/docs/tutorial/sql-databases.md index 20c1367164..b046d14b53 100644 --- a/docs/ko/docs/tutorial/sql-databases.md +++ b/docs/ko/docs/tutorial/sql-databases.md @@ -2,9 +2,9 @@ **FastAPI**에서 SQL(관계형) 데이터베이스 사용은 필수가 아닙니다. 하지만 여러분이 원하는 **어떤 데이터베이스든** 사용할 수 있습니다. -여기서는 SQLModel을 사용하는 예제를 살펴보겠습니다. +여기서는 [SQLModel](https://sqlmodel.tiangolo.com/)을 사용하는 예제를 살펴보겠습니다. -**SQLModel**은 SQLAlchemy와 Pydantic을 기반으로 구축되었습니다. **SQL 데이터베이스**를 사용해야 하는 FastAPI 애플리케이션에 완벽히 어울리도록 **FastAPI**와 같은 제작자가 만든 도구입니다. +**SQLModel**은 [SQLAlchemy](https://www.sqlalchemy.org/)와 Pydantic을 기반으로 구축되었습니다. **SQL 데이터베이스**를 사용해야 하는 FastAPI 애플리케이션에 완벽히 어울리도록 **FastAPI**와 같은 제작자가 만든 도구입니다. /// tip | 팁 @@ -26,15 +26,15 @@ SQLModel은 SQLAlchemy를 기반으로 하므로, SQLAlchemy에서 **지원하 /// tip | 팁 -프론트엔드와 더 많은 도구를 포함하여 **FastAPI**와 **PostgreSQL**을 포함한 공식 프로젝트 생성기가 있습니다: https://github.com/fastapi/full-stack-fastapi-template +프론트엔드와 더 많은 도구를 포함하여 **FastAPI**와 **PostgreSQL**을 포함한 공식 프로젝트 생성기가 있습니다: [https://github.com/fastapi/full-stack-fastapi-template](https://github.com/fastapi/full-stack-fastapi-template) /// -이 튜토리얼은 매우 간단하고 짧습니다. 데이터베이스 기본 개념, SQL, 또는 더 고급 기능에 대해 배우고 싶다면, SQLModel 문서를 참고하세요. +이 튜토리얼은 매우 간단하고 짧습니다. 데이터베이스 기본 개념, SQL, 또는 더 고급 기능에 대해 배우고 싶다면, [SQLModel 문서](https://sqlmodel.tiangolo.com/)를 참고하세요. ## `SQLModel` 설치하기 { #install-sqlmodel } -먼저, [가상 환경](../virtual-environments.md){.internal-link target=_blank}을 생성하고 활성화한 다음, `sqlmodel`을 설치하세요: +먼저, [가상 환경](../virtual-environments.md)을 생성하고 활성화한 다음, `sqlmodel`을 설치하세요:
@@ -65,7 +65,7 @@ $ pip install sqlmodel * `Field(primary_key=True)`는 SQLModel에 `id`가 SQL 데이터베이스의 **기본 키**임을 알려줍니다 (SQL 기본 키에 대한 자세한 내용은 SQLModel 문서를 참고하세요). - **참고:** 기본 키 필드에 `int | None`을 사용하는 이유는, Python 코드에서 *`id` 없이 객체를 생성*할 수 있게 하기 위해서입니다(`id=None`). 데이터베이스가 *저장할 때 생성해 줄 것*이라고 가정합니다. SQLModel은 데이터베이스가 `id`를 제공한다는 것을 이해하고, 데이터베이스 스키마에서 *해당 열을 null이 아닌 `INTEGER`*로 정의합니다. 자세한 내용은 기본 키에 대한 SQLModel 문서를 참고하세요. + **참고:** 기본 키 필드에 `int | None`을 사용하는 이유는, Python 코드에서 *`id` 없이 객체를 생성*할 수 있게 하기 위해서입니다(`id=None`). 데이터베이스가 *저장할 때 생성해 줄 것*이라고 가정합니다. SQLModel은 데이터베이스가 `id`를 제공한다는 것을 이해하고, 데이터베이스 스키마에서 *해당 열을 null이 아닌 `INTEGER`*로 정의합니다. 자세한 내용은 [기본 키에 대한 SQLModel 문서](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id)를 참고하세요. * `Field(index=True)`는 SQLModel에 해당 열에 대해 **SQL 인덱스**를 생성하도록 지시합니다. 이를 통해 데이터베이스에서 이 열로 필터링된 데이터를 읽을 때 더 빠르게 조회할 수 있습니다. @@ -111,7 +111,7 @@ SQLModel의 `engine` (내부적으로는 SQLAlchemy `engine`)은 데이터베이 /// tip | 팁 -SQLModel은 Alembic을 감싸는 마이그레이션 유틸리티를 제공할 예정입니다. 하지만 현재 Alembic을 직접 사용할 수 있습니다. +SQLModel은 Alembic을 감싸는 마이그레이션 유틸리티를 제공할 예정입니다. 하지만 현재 [Alembic](https://alembic.sqlalchemy.org/en/latest/)을 직접 사용할 수 있습니다. /// @@ -152,7 +152,7 @@ SQLModel은 Alembic을 감싸는 마이그레이션 유틸리티를 제공할
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -337,7 +337,7 @@ hero **삭제**는 이전과 거의 동일합니다.
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -352,6 +352,6 @@ $ fastapi dev main.py ## 요약 { #recap } -**SQLModel**을 사용하여 SQL 데이터베이스와 상호작용하고, *데이터 모델* 및 *테이블 모델*로 코드를 간소화할 수 있습니다. +[**SQLModel**](https://sqlmodel.tiangolo.com/)을 사용하여 SQL 데이터베이스와 상호작용하고, *데이터 모델* 및 *테이블 모델*로 코드를 간소화할 수 있습니다. -더 많은 내용을 배우려면 **SQLModel** 문서를 참고하세요. **FastAPI**와 함께 SQLModel을 사용하는 더 긴 미니 튜토리얼도 있습니다. 🚀 +더 많은 내용을 배우려면 **SQLModel** 문서를 참고하세요. **FastAPI**와 함께 SQLModel을 사용하는 더 긴 미니 [튜토리얼](https://sqlmodel.tiangolo.com/tutorial/fastapi/)도 있습니다. 🚀 diff --git a/docs/ko/docs/tutorial/static-files.md b/docs/ko/docs/tutorial/static-files.md index 0235d83c7f..d4c6f6c2d4 100644 --- a/docs/ko/docs/tutorial/static-files.md +++ b/docs/ko/docs/tutorial/static-files.md @@ -23,7 +23,7 @@ 마운트된 애플리케이션은 완전히 독립적이므로 `APIRouter`를 사용하는 것과는 다릅니다. 메인 애플리케이션의 OpenAPI 및 문서에는 마운트된 애플리케이션의 내용 등이 포함되지 않습니다. -자세한 내용은 [고급 사용자 가이드](../advanced/index.md){.internal-link target=_blank}에서 확인할 수 있습니다. +자세한 내용은 [고급 사용자 가이드](../advanced/index.md)에서 확인할 수 있습니다. ## 세부사항 { #details } @@ -37,4 +37,4 @@ ## 추가 정보 { #more-info } -자세한 내용과 옵션은 Starlette의 정적 파일 문서를 확인하세요. +자세한 내용과 옵션은 [Starlette의 정적 파일 문서](https://www.starlette.dev/staticfiles/)를 확인하세요. diff --git a/docs/ko/docs/tutorial/testing.md b/docs/ko/docs/tutorial/testing.md index 57ab811515..aab85580bb 100644 --- a/docs/ko/docs/tutorial/testing.md +++ b/docs/ko/docs/tutorial/testing.md @@ -1,18 +1,18 @@ # 테스팅 { #testing } -Starlette 덕분에 **FastAPI** 애플리케이션을 테스트하는 일은 쉽고 즐거운 일이 되었습니다. +[Starlette](https://www.starlette.dev/testclient/) 덕분에 **FastAPI** 애플리케이션을 테스트하는 일은 쉽고 즐거운 일이 되었습니다. -이는 HTTPX를 기반으로 하며, 이는 Requests를 기반으로 설계되었기 때문에 매우 친숙하고 직관적입니다. +이는 [HTTPX](https://www.python-httpx.org)를 기반으로 하며, 이는 Requests를 기반으로 설계되었기 때문에 매우 친숙하고 직관적입니다. -이를 사용하면 **FastAPI**에서 pytest를 직접 사용할 수 있습니다. +이를 사용하면 **FastAPI**에서 [pytest](https://docs.pytest.org/)를 직접 사용할 수 있습니다. ## `TestClient` 사용하기 { #using-testclient } /// info | 정보 -`TestClient` 사용하려면, 우선 `httpx`를 설치해야 합니다. +`TestClient` 사용하려면, 우선 [`httpx`](https://www.python-httpx.org)를 설치해야 합니다. -[virtual environment](../virtual-environments.md){.internal-link target=_blank}를 만들고, 활성화 시킨 뒤에 설치하세요. 예시: +[가상 환경](../virtual-environments.md)을 만들고, 활성화한 뒤 설치하세요. 예시: ```console $ pip install httpx @@ -52,7 +52,7 @@ $ pip install httpx /// tip | 팁 -FastAPI 애플리케이션에 요청을 보내는 것 외에도 테스트에서 `async` 함수를 호출하고 싶다면 (예: 비동기 데이터베이스 함수), 심화 튜토리얼의 [Async Tests](../advanced/async-tests.md){.internal-link target=_blank}를 참조하세요. +FastAPI 애플리케이션에 요청을 보내는 것 외에도 테스트에서 `async` 함수를 호출하고 싶다면 (예: 비동기 데이터베이스 함수), 심화 튜토리얼의 [비동기 테스트](../advanced/async-tests.md)를 참조하세요. /// @@ -64,7 +64,7 @@ FastAPI 애플리케이션에 요청을 보내는 것 외에도 테스트에서 ### **FastAPI** app 파일 { #fastapi-app-file } -[Bigger Applications](bigger-applications.md){.internal-link target=_blank}에 묘사된 파일 구조를 가지고 있는 것으로 가정해봅시다. +[더 큰 애플리케이션](bigger-applications.md)에 묘사된 파일 구조를 가지고 있는 것으로 가정해봅시다. ``` . @@ -142,13 +142,13 @@ FastAPI 애플리케이션에 요청을 보내는 것 외에도 테스트에서 * *헤더*를 전달하려면, `headers` 파라미터에 `dict`를 전달한다. * *쿠키*를 전달하려면, `cookies` 파라미터에 `dict`를 전달한다. -백엔드로 데이터를 어떻게 보내는지 정보를 더 얻으려면 (`httpx` 혹은 `TestClient`를 이용해서) HTTPX documentation를 확인하세요. +백엔드로 데이터를 어떻게 보내는지 정보를 더 얻으려면 (`httpx` 혹은 `TestClient`를 이용해서) [HTTPX 문서](https://www.python-httpx.org)를 확인하세요. /// info | 정보 `TestClient`는 Pydantic 모델이 아니라 JSON으로 변환될 수 있는 데이터를 받습니다. -만약 테스트 중 Pydantic 모델을 가지고 있고 테스트 중에 애플리케이션으로 해당 데이터를 보내고 싶다면, [JSON Compatible Encoder](encoder.md){.internal-link target=_blank}에 설명되어 있는 `jsonable_encoder`를 사용할 수 있습니다. +만약 테스트 중 Pydantic 모델을 가지고 있고 테스트 중에 애플리케이션으로 해당 데이터를 보내고 싶다면, [JSON 호환 인코더](encoder.md)에 설명되어 있는 `jsonable_encoder`를 사용할 수 있습니다. /// @@ -156,7 +156,7 @@ FastAPI 애플리케이션에 요청을 보내는 것 외에도 테스트에서 그 후에는 `pytest`를 설치하기만 하면 됩니다. -[virtual environment](../virtual-environments.md){.internal-link target=_blank}를 만들고, 활성화 시킨 뒤에 설치하세요. 예시: +[가상 환경](../virtual-environments.md)을 만들고, 활성화 시킨 뒤에 설치하세요. 예시:
diff --git a/docs/ko/docs/virtual-environments.md b/docs/ko/docs/virtual-environments.md index e6baef73b4..7c2a59f81c 100644 --- a/docs/ko/docs/virtual-environments.md +++ b/docs/ko/docs/virtual-environments.md @@ -22,7 +22,7 @@ Python 프로젝트를 작업할 때는 **가상 환경**(또는 이와 유사 이 페이지에서는 **가상 환경**을 사용하는 방법과 작동 방식을 알려드립니다. -Python 설치까지 포함해 **모든 것을 관리해주는 도구**를 도입할 준비가 되었다면 uv를 사용해 보세요. +Python 설치까지 포함해 **모든 것을 관리해주는 도구**를 도입할 준비가 되었다면 [uv](https://github.com/astral-sh/uv)를 사용해 보세요. /// @@ -86,7 +86,7 @@ $ python -m venv .venv //// tab | `uv` -`uv`가 설치되어 있다면, 이를 사용해 가상 환경을 생성할 수 있습니다. +[`uv`](https://github.com/astral-sh/uv)가 설치되어 있다면, 이를 사용해 가상 환경을 생성할 수 있습니다.
@@ -150,7 +150,7 @@ $ .venv\Scripts\Activate.ps1 //// tab | Windows Bash -또는 Windows에서 Bash(예: Git Bash)를 사용하는 경우: +또는 Windows에서 Bash(예: [Git Bash](https://gitforwindows.org/))를 사용하는 경우:
@@ -216,7 +216,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python /// tip -`uv`를 사용한다면, `pip` 대신 `uv`로 설치하게 되므로 `pip`을 업그레이드할 필요가 없습니다. 😎 +[`uv`](https://github.com/astral-sh/uv)를 사용한다면, `pip` 대신 `uv`로 설치하게 되므로 `pip`을 업그레이드할 필요가 없습니다. 😎 /// @@ -268,7 +268,7 @@ $ python -m ensurepip --upgrade /// tip -`uv`로 가상 환경을 만들었다면, 이미 자동으로 처리되어 있으므로 이 단계는 건너뛰어도 됩니다. 😎 +[`uv`](https://github.com/astral-sh/uv)로 가상 환경을 만들었다면, 이미 자동으로 처리되어 있으므로 이 단계는 건너뛰어도 됩니다. 😎 /// @@ -340,7 +340,7 @@ $ pip install "fastapi[standard]" //// tab | `uv` -`uv`가 있다면: +[`uv`](https://github.com/astral-sh/uv)가 있다면:
@@ -372,7 +372,7 @@ $ pip install -r requirements.txt //// tab | `uv` -`uv`가 있다면: +[`uv`](https://github.com/astral-sh/uv)가 있다면:
@@ -416,8 +416,8 @@ Hello World 예를 들면: -* VS Code -* PyCharm +* [VS Code](https://code.visualstudio.com/docs/python/environments#_select-and-activate-an-environment) +* [PyCharm](https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html) /// tip @@ -455,7 +455,7 @@ $ deactivate ## 가상 환경을 왜 사용하나요 { #why-virtual-environments } -FastAPI로 작업하려면 Python을 설치해야 합니다. +FastAPI로 작업하려면 [Python](https://www.python.org/)을 설치해야 합니다. 그 다음 FastAPI와 사용하려는 다른 **패키지**를 **설치**해야 합니다. @@ -564,7 +564,7 @@ $ pip install "fastapi[standard]"
-FastAPI 코드를 담은 압축 파일을 다운로드합니다. 보통 PyPI에서 받습니다. +FastAPI 코드를 담은 압축 파일을 다운로드합니다. 보통 [PyPI](https://pypi.org/project/fastapi/)에서 받습니다. 또한 FastAPI가 의존하는 다른 패키지들의 파일도 **다운로드**합니다. @@ -627,7 +627,7 @@ $ .venv\Scripts\Activate.ps1 //// tab | Windows Bash -또는 Windows에서 Bash(예: Git Bash)를 사용하는 경우: +또는 Windows에서 Bash(예: [Git Bash](https://gitforwindows.org/))를 사용하는 경우:
@@ -639,13 +639,13 @@ $ source .venv/Scripts/activate //// -다음 명령어들에서 사용할 수 있는 몇몇 [환경 변수](environment-variables.md){.internal-link target=_blank}를 생성하거나 수정하는 것을 의미합니다. +다음 명령어들에서 사용할 수 있는 몇몇 [환경 변수](environment-variables.md)를 생성하거나 수정하는 것을 의미합니다. 그 변수 중 하나가 `PATH` 변수입니다. /// tip -`PATH` 환경 변수에 대해 더 알아보려면 [환경 변수](environment-variables.md#path-environment-variable){.internal-link target=_blank} 섹션을 참고하세요. +`PATH` 환경 변수에 대해 더 알아보려면 [환경 변수](environment-variables.md#path-environment-variable) 섹션을 참고하세요. /// @@ -846,7 +846,7 @@ I solemnly swear 🐺 가상 환경, 패키지 의존성(requirements), 프로젝트를 관리하는 방법에는 많은 **대안**이 있습니다. -준비가 되었고 **프로젝트 전체**, 패키지 의존성, 가상 환경 등을 **관리**하는 도구를 사용하고 싶다면 uv를 사용해 보시길 권합니다. +준비가 되었고 **프로젝트 전체**, 패키지 의존성, 가상 환경 등을 **관리**하는 도구를 사용하고 싶다면 [uv](https://github.com/astral-sh/uv)를 사용해 보시길 권합니다. `uv`는 많은 일을 할 수 있습니다. 예를 들어: From 92cc0bd9de62c9bdf5116e88a70d5bffaccb2ccb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Mar 2026 14:07:04 +0000 Subject: [PATCH 02/69] =?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 294f73edd2..d9bb22b7b3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Translations +* 🌐 Update translations for ko (update-outdated). PR [#15170](https://github.com/fastapi/fastapi/pull/15170) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for tr (update-outdated). PR [#15172](https://github.com/fastapi/fastapi/pull/15172) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (add-missing). PR [#15168](https://github.com/fastapi/fastapi/pull/15168) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ja (add-missing). PR [#15167](https://github.com/fastapi/fastapi/pull/15167) by [@tiangolo](https://github.com/tiangolo). From 311ce1cfa5bb3e2951010accd7478748c92f9476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 20 Mar 2026 15:07:17 +0100 Subject: [PATCH 03/69] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20fo?= =?UTF-8?q?r=20ja=20(update-outdated)=20(#15171)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov --- docs/ja/docs/_llm-test.md | 16 +- docs/ja/docs/advanced/additional-responses.md | 4 +- .../docs/advanced/additional-status-codes.md | 2 +- .../ja/docs/advanced/advanced-dependencies.md | 4 +- docs/ja/docs/advanced/async-tests.md | 10 +- docs/ja/docs/advanced/behind-a-proxy.md | 26 +-- docs/ja/docs/advanced/custom-response.md | 212 +++++++----------- docs/ja/docs/advanced/dataclasses.md | 8 +- docs/ja/docs/advanced/events.md | 6 +- docs/ja/docs/advanced/generate-clients.md | 18 +- docs/ja/docs/advanced/index.md | 4 +- docs/ja/docs/advanced/middleware.md | 10 +- docs/ja/docs/advanced/openapi-callbacks.md | 10 +- docs/ja/docs/advanced/openapi-webhooks.md | 2 +- .../path-operation-advanced-configuration.md | 6 +- .../advanced/response-change-status-code.md | 4 +- docs/ja/docs/advanced/response-cookies.md | 4 +- docs/ja/docs/advanced/response-directly.md | 38 +++- docs/ja/docs/advanced/response-headers.md | 6 +- .../docs/advanced/security/http-basic-auth.md | 4 +- docs/ja/docs/advanced/security/index.md | 6 +- .../docs/advanced/security/oauth2-scopes.md | 4 +- docs/ja/docs/advanced/settings.md | 16 +- docs/ja/docs/advanced/sub-applications.md | 10 +- docs/ja/docs/advanced/templates.md | 4 +- docs/ja/docs/advanced/testing-websockets.md | 2 +- .../docs/advanced/using-request-directly.md | 4 +- docs/ja/docs/advanced/websockets.md | 24 +- docs/ja/docs/advanced/wsgi.md | 6 +- docs/ja/docs/alternatives.md | 58 ++--- docs/ja/docs/async.md | 24 +- docs/ja/docs/benchmarks.md | 2 +- docs/ja/docs/deployment/cloud.md | 8 +- docs/ja/docs/deployment/concepts.md | 12 +- docs/ja/docs/deployment/docker.md | 44 ++-- docs/ja/docs/deployment/fastapicloud.md | 4 +- docs/ja/docs/deployment/https.md | 22 +- docs/ja/docs/deployment/index.md | 2 +- docs/ja/docs/deployment/manually.md | 14 +- docs/ja/docs/deployment/server-workers.md | 6 +- docs/ja/docs/deployment/versions.md | 6 +- docs/ja/docs/environment-variables.md | 46 ++-- docs/ja/docs/fastapi-cli.md | 71 +++++- docs/ja/docs/features.md | 30 +-- docs/ja/docs/help-fastapi.md | 60 ++--- docs/ja/docs/history-design-future.md | 12 +- .../authentication-error-status-code.md | 2 +- docs/ja/docs/how-to/conditional-openapi.md | 2 +- docs/ja/docs/how-to/configure-swagger-ui.md | 4 +- docs/ja/docs/how-to/custom-docs-ui-assets.md | 12 +- .../docs/how-to/custom-request-and-route.md | 8 +- docs/ja/docs/how-to/extending-openapi.md | 4 +- docs/ja/docs/how-to/general.md | 22 +- docs/ja/docs/how-to/graphql.md | 30 +-- docs/ja/docs/how-to/index.md | 2 +- ...migrate-from-pydantic-v1-to-pydantic-v2.md | 8 +- docs/ja/docs/how-to/testing-database.md | 6 +- docs/ja/docs/index.md | 118 +++++----- docs/ja/docs/project-generation.md | 2 +- docs/ja/docs/python-types.md | 12 +- docs/ja/docs/tutorial/background-tasks.md | 6 +- docs/ja/docs/tutorial/bigger-applications.md | 69 ++++-- docs/ja/docs/tutorial/body-nested-models.md | 2 +- docs/ja/docs/tutorial/body-updates.md | 8 +- docs/ja/docs/tutorial/body.md | 12 +- docs/ja/docs/tutorial/cors.md | 8 +- docs/ja/docs/tutorial/debugging.md | 4 +- ...pendencies-in-path-operation-decorators.md | 4 +- .../dependencies/dependencies-with-yield.md | 20 +- .../dependencies/global-dependencies.md | 6 +- docs/ja/docs/tutorial/dependencies/index.md | 4 +- docs/ja/docs/tutorial/encoder.md | 4 +- docs/ja/docs/tutorial/extra-data-types.md | 4 +- docs/ja/docs/tutorial/extra-models.md | 6 +- docs/ja/docs/tutorial/first-steps.md | 77 +++++-- docs/ja/docs/tutorial/handling-errors.md | 2 +- docs/ja/docs/tutorial/index.md | 12 +- docs/ja/docs/tutorial/metadata.md | 4 +- docs/ja/docs/tutorial/middleware.md | 10 +- .../tutorial/path-operation-configuration.md | 2 +- .../path-params-numeric-validations.md | 4 +- docs/ja/docs/tutorial/path-params.md | 16 +- .../tutorial/query-params-str-validations.md | 12 +- docs/ja/docs/tutorial/query-params.md | 2 +- docs/ja/docs/tutorial/request-files.md | 12 +- docs/ja/docs/tutorial/request-form-models.md | 6 +- .../docs/tutorial/request-forms-and-files.md | 4 +- docs/ja/docs/tutorial/request-forms.md | 6 +- docs/ja/docs/tutorial/response-model.md | 9 +- docs/ja/docs/tutorial/response-status-code.md | 8 +- docs/ja/docs/tutorial/schema-extra-example.md | 8 +- docs/ja/docs/tutorial/security/first-steps.md | 10 +- docs/ja/docs/tutorial/security/oauth2-jwt.md | 10 +- .../docs/tutorial/security/simple-oauth2.md | 6 +- docs/ja/docs/tutorial/sql-databases.md | 22 +- docs/ja/docs/tutorial/static-files.md | 4 +- docs/ja/docs/tutorial/testing.md | 28 +-- docs/ja/docs/virtual-environments.md | 30 +-- 98 files changed, 846 insertions(+), 738 deletions(-) diff --git a/docs/ja/docs/_llm-test.md b/docs/ja/docs/_llm-test.md index b3d9fc28cd..4c84a7c04c 100644 --- a/docs/ja/docs/_llm-test.md +++ b/docs/ja/docs/_llm-test.md @@ -11,7 +11,7 @@ * 翻訳が問題ないか確認します。 * 必要であれば、言語固有プロンプト、general プロンプト、または英語ドキュメントを改善します。 * その後、翻訳に残っている問題を手動で修正し、良い翻訳にします。 -* 良い翻訳を用意した状態でもう一度翻訳します。理想的な結果は、LLM が翻訳に一切変更を加えないことです。つまり general プロンプトと言語固有プロンプトが最良であることを意味します(時々いくつかランダムに見える変更を行うことがあります。理由は LLM は決定論的アルゴリズムではない ためです)。 +* 良い翻訳を用意した状態でもう一度翻訳します。理想的な結果は、LLM が翻訳に一切変更を加えないことです。つまり general プロンプトと言語固有プロンプトが最良であることを意味します(時々いくつかランダムに見える変更を行うことがあります。理由は [LLM は決定論的アルゴリズムではない](https://doublespeak.chat/#/handbook#deterministic-output) ためです)。 テスト内容: @@ -95,7 +95,7 @@ $ fastapi run 外部リンク -* スタイルへのリンク -* スクリプトへのリンク -* 画像へのリンク +* [内部リンク](index.md#installation) +* [外部リンク](https://sqlmodel.tiangolo.com/) +* [スタイルへのリンク](https://fastapi.tiangolo.com/css/styles.css) +* [スクリプトへのリンク](https://fastapi.tiangolo.com/js/logic.js) +* [画像へのリンク](https://fastapi.tiangolo.com/img/foo.jpg) リンクのテキストは翻訳し、リンク先のアドレスは翻訳版を指すようにしてください: -* FastAPI リンク +* [FastAPI リンク](https://fastapi.tiangolo.com/ja/) //// diff --git a/docs/ja/docs/advanced/additional-responses.md b/docs/ja/docs/advanced/additional-responses.md index 4c44257885..1d7c2f80e1 100644 --- a/docs/ja/docs/advanced/additional-responses.md +++ b/docs/ja/docs/advanced/additional-responses.md @@ -243,5 +243,5 @@ new_dict = {**old_dict, "new key": "new value"} レスポンスに正確に何を含められるかは、OpenAPI 仕様の次のセクションを参照してください: -- OpenAPI の Responses Object。ここには `Response Object` が含まれます。 -- OpenAPI の Response Object。`responses` パラメータ内の各レスポンスに、ここで定義されている要素を直接含められます。`description`、`headers`、`content`(ここで異なるメディアタイプや JSON Schema を宣言します)、`links` など。 +- [OpenAPI の Responses Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object)、ここには `Response Object` が含まれます。 +- [OpenAPI の Response Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object)、`responses` パラメータ内の各レスポンスに、ここで定義されている要素を直接含められます。`description`、`headers`、`content`(ここで異なるメディアタイプや JSON Schema を宣言します)、`links` など。 diff --git a/docs/ja/docs/advanced/additional-status-codes.md b/docs/ja/docs/advanced/additional-status-codes.md index fdac52e837..ad9bd57dcd 100644 --- a/docs/ja/docs/advanced/additional-status-codes.md +++ b/docs/ja/docs/advanced/additional-status-codes.md @@ -38,4 +38,4 @@ 追加のステータスコードとレスポンスを直接返す場合、それらは OpenAPI スキーマ(API ドキュメント)には含まれません。FastAPI には、事前に何が返されるかを知る方法がないからです。 -しかし、[追加のレスポンス](additional-responses.md){.internal-link target=_blank} を使ってコード内にドキュメント化できます。 +しかし、[追加のレスポンス](additional-responses.md) を使ってコード内にドキュメント化できます。 diff --git a/docs/ja/docs/advanced/advanced-dependencies.md b/docs/ja/docs/advanced/advanced-dependencies.md index d38ce548d1..5181e39d82 100644 --- a/docs/ja/docs/advanced/advanced-dependencies.md +++ b/docs/ja/docs/advanced/advanced-dependencies.md @@ -132,7 +132,7 @@ SQLModel(または SQLAlchemy)でこの特定のユースケースがある このようにすると、セッションはデータベース接続を解放するため、他のリクエストがそれを使えるようになります。 -`yield` を持つ依存関係で早期終了が必要な別のユースケースがある場合は、あなたの具体的なユースケースと、なぜ `yield` を持つ依存関係の早期クローズが有益かを説明して、GitHub Discussion の質問を作成してください。 +`yield` を持つ依存関係で早期終了が必要な別のユースケースがある場合は、あなたの具体的なユースケースと、なぜ `yield` を持つ依存関係の早期クローズが有益かを説明して、[GitHub Discussion の質問](https://github.com/fastapi/fastapi/discussions/new?category=questions)を作成してください。 `yield` を持つ依存関係の早期クローズに納得できるユースケースがある場合は、早期クローズにオプトインする新しい方法を追加することを検討します。 @@ -144,7 +144,7 @@ FastAPI 0.110.0 より前では、`yield` を持つ依存関係を使い、そ ### バックグラウンドタスクと `yield` を伴う依存関係、技術詳細 { #background-tasks-and-dependencies-with-yield-technical-details } -FastAPI 0.106.0 より前では、`yield` の後で例外を送出することはできませんでした。`yield` を持つ依存関係の終了コードはレスポンス送信「後」に実行されるため、[例外ハンドラ](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} はすでに実行済みでした。 +FastAPI 0.106.0 より前では、`yield` の後で例外を送出することはできませんでした。`yield` を持つ依存関係の終了コードはレスポンス送信「後」に実行されるため、[例外ハンドラ](../tutorial/handling-errors.md#install-custom-exception-handlers)はすでに実行済みでした。 これは主に、依存関係が "yield" した同じオブジェクトをバックグラウンドタスク内で利用できるようにするための設計でした。終了コードはバックグラウンドタスク完了後に実行されるからです。 diff --git a/docs/ja/docs/advanced/async-tests.md b/docs/ja/docs/advanced/async-tests.md index 067e9cc9a2..da2968dbf7 100644 --- a/docs/ja/docs/advanced/async-tests.md +++ b/docs/ja/docs/advanced/async-tests.md @@ -16,11 +16,11 @@ `TestClient` は、標準の pytest を使って通常の `def` のテスト関数から非同期の FastAPI アプリを呼び出すための「おまじない」を内部で行います。しかし、その「おまじない」はテスト関数自体が非同期の場合には機能しません。テストを非同期で実行すると、テスト関数内で `TestClient` は使えなくなります。 -`TestClient` は HTTPX を基に作られており、幸いなことに API のテストには HTTPX を直接利用できます。 +`TestClient` は [HTTPX](https://www.python-httpx.org) を基に作られており、幸いなことに API のテストには HTTPX を直接利用できます。 ## 例 { #example } -簡単な例として、[大きなアプリケーション](../tutorial/bigger-applications.md){.internal-link target=_blank} と [テスト](../tutorial/testing.md){.internal-link target=_blank} で説明したものに似たファイル構成を考えます: +簡単な例として、[大きなアプリケーション](../tutorial/bigger-applications.md) と [テスト](../tutorial/testing.md) で説明したものに似たファイル構成を考えます: ``` . @@ -60,7 +60,7 @@ $ pytest /// tip | 豆知識 -`TestClient` を使っていたときと異なり、テスト関数は `def` ではなく `async def` になっている点に注意してください。 +`TestClient` を使っていたときと異なり、テスト関数は `async def` ではなく `def` になっている点に注意してください。 /// @@ -84,7 +84,7 @@ response = client.get('/') /// warning | 注意 -アプリケーションが lifespan イベントに依存している場合、`AsyncClient` はそれらのイベントをトリガーしません。確実にトリガーするには、florimondmanca/asgi-lifespan の `LifespanManager` を使用してください。 +アプリケーションが lifespan イベントに依存している場合、`AsyncClient` はそれらのイベントをトリガーしません。確実にトリガーするには、[florimondmanca/asgi-lifespan](https://github.com/florimondmanca/asgi-lifespan#usage) の `LifespanManager` を使用してください。 /// @@ -94,6 +94,6 @@ response = client.get('/') /// tip | 豆知識 -テストに非同期関数呼び出しを統合した際に(例: MongoDB の MotorClient 使用時)、`RuntimeError: Task attached to a different loop` に遭遇した場合は、イベントループを必要とするオブジェクトは非同期関数内でのみインスタンス化するようにしてください。例えば `@app.on_event("startup")` コールバック内で行います。 +テストに非同期関数呼び出しを統合した際に(例: [MongoDB の MotorClient](https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop) 使用時)、`RuntimeError: Task attached to a different loop` に遭遇した場合は、イベントループを必要とするオブジェクトは非同期関数内でのみインスタンス化するようにしてください。例えば `@app.on_event("startup")` コールバック内で行います。 /// diff --git a/docs/ja/docs/advanced/behind-a-proxy.md b/docs/ja/docs/advanced/behind-a-proxy.md index 67eaa99092..108c437709 100644 --- a/docs/ja/docs/advanced/behind-a-proxy.md +++ b/docs/ja/docs/advanced/behind-a-proxy.md @@ -16,9 +16,9 @@ プロキシのヘッダーは次のとおりです: -* X-Forwarded-For -* X-Forwarded-Proto -* X-Forwarded-Host +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) /// @@ -60,7 +60,7 @@ https://mysuperapp.com/items/ /// tip | 豆知識 -HTTPS について詳しく知りたい場合は、[HTTPS について](../deployment/https.md){.internal-link target=_blank} を参照してください。 +HTTPS について詳しく知りたい場合は、[HTTPS について](../deployment/https.md) を参照してください。 /// @@ -228,7 +228,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 サーバー(Uvicorn)は、その `root_path` をアプリに渡す以外の用途では使用しない点に注意してください。 -しかし、ブラウザで http://127.0.0.1:8000/app にアクセスすると、通常どおりのレスポンスが表示されます: +しかし、ブラウザで [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app) にアクセスすると、通常どおりのレスポンスが表示されます: ```JSON { @@ -251,9 +251,9 @@ Uvicorn は、プロキシが `http://127.0.0.1:8000/app` にアクセスして ## Traefik を使ったローカル検証 { #testing-locally-with-traefik } -Traefik を使えば、パスプレフィックスを削除する構成をローカルで簡単に試せます。 +[Traefik](https://docs.traefik.io/) を使えば、パスプレフィックスを削除する構成をローカルで簡単に試せます。 -Traefik をダウンロード してください。単一バイナリなので、圧縮ファイルを展開して端末から直接実行できます。 +[Traefik をダウンロード](https://github.com/containous/traefik/releases) してください。単一バイナリなので、圧縮ファイルを展開して端末から直接実行できます。 次の内容で `traefik.toml` というファイルを作成します: @@ -330,7 +330,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 ### レスポンスの確認 { #check-the-responses } -ここで、Uvicorn のポートの URL http://127.0.0.1:8000/app にアクセスすると、通常どおりのレスポンスが表示されます: +ここで、Uvicorn のポートの URL [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app) にアクセスすると、通常どおりのレスポンスが表示されます: ```JSON { @@ -345,7 +345,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 /// -次に、Traefik のポートでプレフィックス付きの URL http://127.0.0.1:9999/api/v1/app を開きます。 +次に、Traefik のポートでプレフィックス付きの URL [http://127.0.0.1:9999/api/v1/app](http://127.0.0.1:9999/api/v1/app) を開きます。 同じレスポンスが得られます: @@ -370,13 +370,13 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 「公式な」アクセス方法は、定義したパスプレフィックス付きのプロキシ経由です。したがって想定どおり、プレフィックスなしの URL で Uvicorn が直接提供するドキュメント UI にアクセスすると動作しません。プロキシ経由でアクセスされることを前提としているためです。 -http://127.0.0.1:8000/docs を確認してください: +[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) を確認してください: しかし、プロキシ(ポート `9999`)を使った「公式」URL `/api/v1/docs` でドキュメント UI にアクセスすると、正しく動作します!🎉 -http://127.0.0.1:9999/api/v1/docs を確認してください: +[http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs) を確認してください: @@ -433,7 +433,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 /// -ドキュメント UI(http://127.0.0.1:9999/api/v1/docs)では次のように表示されます: +ドキュメント UI([http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs))では次のように表示されます: @@ -461,6 +461,6 @@ OpenAPI 仕様の `servers` プロパティは任意です。 ## サブアプリケーションのマウント { #mounting-a-sub-application } -`root_path` を伴うプロキシを使用しつつサブアプリケーションをマウントする必要がある場合でも([サブアプリケーション - マウント](sub-applications.md){.internal-link target=_blank} 参照)、通常どおりに行えます。 +`root_path` を伴うプロキシを使用しつつサブアプリケーションをマウントする必要がある場合でも([サブアプリケーション - マウント](sub-applications.md) 参照)、通常どおりに行えます。 FastAPI は内部で `root_path` を適切に扱うため、そのまま動作します。✨ diff --git a/docs/ja/docs/advanced/custom-response.md b/docs/ja/docs/advanced/custom-response.md index 50a7891658..e66b1f4944 100644 --- a/docs/ja/docs/advanced/custom-response.md +++ b/docs/ja/docs/advanced/custom-response.md @@ -1,150 +1,134 @@ -# カスタムレスポンス - HTML、ストリーム、ファイル、その他のレスポンス { #custom-response-html-stream-file-others } +# カスタムレスポンス - HTML、ストリーム、ファイル、その他 { #custom-response-html-stream-file-others } -デフォルトでは、**FastAPI** は `JSONResponse` を使ってレスポンスを返します。 +デフォルトでは、**FastAPI** はJSONレスポンスを返します。 -[レスポンスを直接返す](response-directly.md){.internal-link target=_blank}で見たように、 `Response` を直接返すことでこの挙動をオーバーライドできます。 +[レスポンスを直接返す](response-directly.md)で見たように、`Response` を直接返してこの挙動を上書きできます。 -しかし、`Response` を直接返すと(または `JSONResponse` のような任意のサブクラスを返すと)、データは自動的に変換されず(`response_model` を宣言していても)、ドキュメントも自動生成されません(例えば、生成されるOpenAPIの一部としてHTTPヘッダー `Content-Type` に特定の「メディアタイプ」を含めるなど)。 +しかし、`Response`(または `JSONResponse` のような任意のサブクラス)を直接返す場合、(`response_model` を宣言していても)データは自動的に変換されず、ドキュメントも自動生成されません(例えば、生成されるOpenAPIの一部としてHTTPヘッダー `Content-Type` に特定の「メディアタイプ」を含めるなど)。 -`response_class` パラメータを使用して、*path operation デコレータ* で使用したい `Response`(任意の `Response` サブクラス)を宣言することもできます。 +一方で、*path operation デコレータ* の `response_class` パラメータを使って、使用したい `Response`(`Response` の任意のサブクラス)を宣言することもできます。 -*path operation 関数* から返されるコンテンツは、その `Response` に含まれます。 - -そしてその `Response` が、`JSONResponse` や `UJSONResponse` の場合のようにJSONメディアタイプ(`application/json`)なら、関数の返り値は *path operationデコレータ* に宣言した任意のPydantic `response_model` により自動的に変換(およびフィルタ)されます。 +*path operation 関数* から返したコンテンツは、その `Response` に格納されます。 /// note | 備考 -メディアタイプを指定せずにレスポンスクラスを利用すると、FastAPIはレスポンスにコンテンツがないことを期待します。そのため、生成されるOpenAPIドキュメントにレスポンスフォーマットが記載されません。 +メディアタイプを持たないレスポンスクラスを使用すると、FastAPIはレスポンスにコンテンツがないものと見なします。そのため、生成されるOpenAPIドキュメントにレスポンスフォーマットは記載されません。 /// -## `ORJSONResponse` を使う { #use-orjsonresponse } - -例えば、パフォーマンスを絞り出したい場合は、`orjson`をインストールし、レスポンスとして `ORJSONResponse` をセットできます。 - -使いたい `Response` クラス(サブクラス)をインポートし、*path operationデコレータ* に宣言します。 +## JSONレスポンス { #json-responses } -大きなレスポンスの場合、`Response` を直接返すほうが、辞書を返すよりもはるかに高速です。 +FastAPI はデフォルトでJSONレスポンスを返します。 -これは、デフォルトではFastAPIがチュートリアルで説明した同じ[JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}を使って、内部の各アイテムを検査し、JSONとしてシリアライズ可能であることを確認するためです。これにより、例えばデータベースモデルのような**任意のオブジェクト**を返せます。 +[レスポンスモデル](../tutorial/response-model.md) を宣言すると、FastAPI は Pydantic を使ってデータをJSONにシリアライズします。 -しかし、返そうとしているコンテンツが **JSONでシリアライズ可能**であることが確実なら、それを直接レスポンスクラスに渡して、FastAPIがレスポンスクラスへ渡す前に返却コンテンツを `jsonable_encoder` に通すことで発生する追加のオーバーヘッドを回避できます。 - -{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} - -/// info | 情報 +レスポンスモデルを宣言しない場合、FastAPI は [JSON Compatible Encoder](../tutorial/encoder.md) で説明した `jsonable_encoder` を使い、その結果を `JSONResponse` に入れます。 -パラメータ `response_class` は、レスポンスの「メディアタイプ」を定義するためにも利用されます。 +`JSONResponse` のようにJSONメディアタイプ(`application/json`)を持つ `response_class` を宣言した場合、*path operation デコレータ* に宣言した任意のPydanticの `response_model` に従って、返すデータは自動的に変換(およびフィルタ)されます。ただし、そのデータは Pydantic でJSONのバイト列にシリアライズされるわけではなく、まず `jsonable_encoder` で変換された後に `JSONResponse` クラスへ渡され、Pythonの標準JSONライブラリでバイト列にシリアライズされます。 -この場合、HTTPヘッダー `Content-Type` には `application/json` がセットされます。 - -そして、OpenAPIにはそのようにドキュメントされます。 - -/// - -/// tip | 豆知識 +### JSONのパフォーマンス { #json-performance } -`ORJSONResponse` はFastAPIでのみ利用可能で、Starletteでは利用できません。 +結論として、最大のパフォーマンスを得たい場合は、[レスポンスモデル](../tutorial/response-model.md) を使い、*path operation デコレータ* で `response_class` は宣言しないでください。 -/// +{* ../../docs_src/response_model/tutorial001_01_py310.py ln[15:17] hl[16] *} ## HTMLレスポンス { #html-response } -**FastAPI** からHTMLを直接返す場合は、`HTMLResponse` を使います。 +**FastAPI** からHTMLを直接返すには、`HTMLResponse` を使います。 -* `HTMLResponse` をインポートする。 -* *path operation デコレータ* のパラメータ `response_class` に `HTMLResponse` を渡す。 +* `HTMLResponse` をインポートする +* *path operation デコレータ* のパラメータ `response_class` に `HTMLResponse` を渡す {* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} /// info | 情報 -パラメータ `response_class` は、レスポンスの「メディアタイプ」を定義するためにも利用されます。 +パラメータ `response_class` は、レスポンスの「メディアタイプ」を定義するためにも使用されます。 -この場合、HTTPヘッダー `Content-Type` には `text/html` がセットされます。 +この場合、HTTPヘッダー `Content-Type` には `text/html` が設定されます。 -そして、OpenAPIにはそのようにドキュメントされます。 +そして、OpenAPIにもそのようにドキュメント化されます。 /// ### `Response` を返す { #return-a-response } -[レスポンスを直接返す](response-directly.md){.internal-link target=_blank}で見たように、レスポンスを返すことで、*path operation* の中でレスポンスを直接オーバーライドすることもできます。 +[レスポンスを直接返す](response-directly.md)で見たように、*path operation* の中でレスポンスを直接返して上書きすることもできます。 -上記と同じ例において、 `HTMLResponse` を返すと、このようになります: +上記と同じ例で、`HTMLResponse` を返すと次のようになります: {* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} /// warning | 注意 -*path operation関数* から直接返される `Response` は、OpenAPIにドキュメントされず(例えば、`Content-Type` がドキュメントされない)、自動的な対話的ドキュメントでも表示されません。 +*path operation 関数* から直接返される `Response` は、OpenAPIにドキュメント化されず(例えば `Content-Type` がドキュメント化されない)、自動生成の対話的ドキュメントにも表示されません。 /// /// info | 情報 -もちろん、実際の `Content-Type` ヘッダーやステータスコードなどは、返された `Response` オブジェクトに由来します。 +もちろん、実際の `Content-Type` ヘッダーやステータスコードなどは、返した `Response` オブジェクトに由来します。 /// -### OpenAPIドキュメントと `Response` のオーバーライド { #document-in-openapi-and-override-response } +### OpenAPIにドキュメント化しつつ `Response` を上書き { #document-in-openapi-and-override-response } -関数の中でレスポンスをオーバーライドしつつも、OpenAPI に「メディアタイプ」をドキュメント化したいなら、`response_class` パラメータを使用し、かつ `Response` オブジェクトを返します。 +関数の中からレスポンスを上書きしつつ、同時にOpenAPIで「メディアタイプ」をドキュメント化したい場合は、`response_class` パラメータを使用し、かつ `Response` オブジェクトを返します。 -`response_class` はOpenAPIの*path operation*のドキュメント化のためにのみ使用され、`Response` はそのまま使用されます。 +この場合、`response_class` はOpenAPIの *path operation* をドキュメント化するためだけに使われ、実際には返した `Response` がそのまま使用されます。 #### `HTMLResponse` を直接返す { #return-an-htmlresponse-directly } -例えば、このようになります: +例えば、次のようになります: {* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} -この例では、関数 `generate_html_response()` は、`str` のHTMLを返すのではなく、`Response` を生成して返しています。 +この例では、関数 `generate_html_response()` はHTMLの `str` を返すのではなく、すでに `Response` を生成して返しています。 -`generate_html_response()` を呼び出した結果を返すことにより、デフォルトの **FastAPI** の挙動をオーバーライドする `Response` をすでに返しています。 +`generate_html_response()` の呼び出し結果を返すことで、デフォルトの **FastAPI** の挙動を上書きする `Response` をすでに返しています。 -しかし、`response_class` にも `HTMLResponse` を渡しているため、**FastAPI** はOpenAPIと対話的ドキュメントで、`text/html` のHTMLとしてどのようにドキュメント化すればよいかを理解できます: +しかし、`response_class` にも `HTMLResponse` を渡しているため、**FastAPI** はOpenAPIおよび対話的ドキュメントで、それが `text/html` のHTMLであると正しくドキュメント化できます: ## 利用可能なレスポンス { #available-responses } -以下が利用可能なレスポンスの一部です。 +以下は利用可能なレスポンスの一部です。 -`Response` を使って他の何かを返せますし、カスタムのサブクラスも作れることを覚えておいてください。 +`Response` を使って他のものを返したり、カスタムサブクラスを作成することもできます。 /// note | 技術詳細 -`from starlette.responses import HTMLResponse` も利用できます。 +`from starlette.responses import HTMLResponse` を使うこともできます。 -**FastAPI** は開発者の利便性のために、`starlette.responses` と同じものを `fastapi.responses` として提供しています。しかし、利用可能なレスポンスのほとんどはStarletteから直接提供されます。 +**FastAPI** は開発者の利便性のために、`starlette.responses` と同じものを `fastapi.responses` として提供しています。ただし、利用可能なレスポンスの多くはStarletteから直接提供されています。 /// ### `Response` { #response } -メインの `Response` クラスで、他の全てのレスポンスはこれを継承しています。 +メインの `Response` クラスで、他のすべてのレスポンスはこれを継承しています。 直接返すことができます。 以下のパラメータを受け付けます。 -* `content` - `str` か `bytes`。 -* `status_code` - `int` のHTTPステータスコード。 -* `headers` - 文字列の `dict` 。 -* `media_type` - メディアタイプを示す `str` 。例えば `"text/html"` 。 +* `content` - `str` または `bytes` +* `status_code` - `int` のHTTPステータスコード +* `headers` - 文字列の `dict` +* `media_type` - メディアタイプを示す `str`。例: `"text/html"` -FastAPI(実際にはStarlette)は自動的にContent-Lengthヘッダーを含みます。また、`media_type` に基づいたContent-Typeヘッダーを含み、テキストタイプのためにcharsetを追加します。 +FastAPI(実際にはStarlette)は自動的に Content-Length ヘッダーを含めます。また、`media_type` に基づいた Content-Type ヘッダーを含め、テキストタイプには charset を追加します。 {* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} ### `HTMLResponse` { #htmlresponse } -上で読んだように、テキストやバイトを受け取り、HTMLレスポンスを返します。 +上で読んだように、テキストやバイト列を受け取り、HTMLレスポンスを返します。 ### `PlainTextResponse` { #plaintextresponse } -テキストやバイトを受け取り、プレーンテキストのレスポンスを返します。 +テキストやバイト列を受け取り、プレーンテキストのレスポンスを返します。 {* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} @@ -152,45 +136,19 @@ FastAPI(実際にはStarlette)は自動的にContent-Lengthヘッダーを データを受け取り、`application/json` としてエンコードされたレスポンスを返します。 -上で読んだように、**FastAPI** のデフォルトのレスポンスとして利用されます。 - -### `ORJSONResponse` { #orjsonresponse } - -上で読んだように、`orjson`を使った、高速な代替のJSONレスポンスです。 - -/// info | 情報 - -これは、例えば `pip install orjson` で `orjson` をインストールする必要があります。 +これは、上で述べたように **FastAPI** のデフォルトのレスポンスです。 -/// - -### `UJSONResponse` { #ujsonresponse } - -`ujson`を使った、代替のJSONレスポンスです。 - -/// info | 情報 - -これは、例えば `pip install ujson` で `ujson` をインストールする必要があります。 - -/// - -/// warning | 注意 - -`ujson` は、いくつかのエッジケースの取り扱いについて、Pythonにビルトインされた実装ほど注意深くありません。 - -/// - -{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} +/// note | 技術詳細 -/// tip | 豆知識 +ただし、レスポンスモデルや返却型を宣言した場合は、それが直接データのJSONシリアライズに使われ、適切なJSONのメディアタイプを持つレスポンスが `JSONResponse` クラスを使わずに直接返されます。 -`ORJSONResponse` のほうが高速な代替かもしれません。 +これが最適なパフォーマンスを得る理想的な方法です。 /// ### `RedirectResponse` { #redirectresponse } -HTTPリダイレクトを返します。デフォルトでは307ステータスコード(Temporary Redirect)となります。 +HTTPリダイレクトを返します。デフォルトでは307ステータスコード(Temporary Redirect)を使用します。 `RedirectResponse` を直接返せます: @@ -202,56 +160,50 @@ HTTPリダイレクトを返します。デフォルトでは307ステータス {* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} -その場合、*path operation*関数からURLを直接返せます。 +その場合、*path operation* 関数からURLを直接返せます。 -この場合に使用される `status_code` は `RedirectResponse` のデフォルトである `307` になります。 +この場合に使用される `status_code` は、`RedirectResponse` のデフォルトである `307` になります。 --- -また、`status_code` パラメータを `response_class` パラメータと組み合わせて使うこともできます: +さらに、`status_code` パラメータを `response_class` パラメータと組み合わせて使うこともできます: {* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} ### `StreamingResponse` { #streamingresponse } -非同期ジェネレータ、または通常のジェネレータ/イテレータを受け取り、レスポンスボディをストリームします。 +非同期ジェネレータ、または通常のジェネレータ/イテレータ(`yield` を持つ関数)を受け取り、レスポンスボディをストリームします。 -{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} +{* ../../docs_src/custom_response/tutorial007_py310.py hl[3,16] *} -#### ファイルライクオブジェクトで `StreamingResponse` を使う { #using-streamingresponse-with-file-like-objects } - -file-like オブジェクト(例: `open()` で返されるオブジェクト)がある場合、そのfile-likeオブジェクトを反復処理するジェネレータ関数を作れます。 - -そうすれば、最初にすべてをメモリへ読み込む必要はなく、そのジェネレータ関数を `StreamingResponse` に渡して返せます。 - -これにはクラウドストレージとの連携、映像処理など、多くのライブラリが含まれます。 +/// note | 技術詳細 -{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} +`async` タスクは `await` に到達したときにのみキャンセルできます。`await` がない場合、ジェネレータ(`yield` を持つ関数)は適切にキャンセルできず、キャンセル要求後も実行が続く可能性があります。 -1. これはジェネレータ関数です。内部に `yield` 文を含むため「ジェネレータ関数」です。 -2. `with` ブロックを使うことで、ジェネレータ関数が終わった後(つまりレスポンスの送信が完了した後)にfile-likeオブジェクトが確実にクローズされるようにします。 -3. この `yield from` は、`file_like` という名前のものを反復処理するように関数へ指示します。そして反復された各パートについて、そのパートをこのジェネレータ関数(`iterfile`)から来たものとして `yield` します。 +この小さな例では `await` が不要なため、イベントループにキャンセルを処理する機会を与えるために `await anyio.sleep(0)` を追加しています。 - つまり、内部的に「生成」の作業を別のものへ移譲するジェネレータ関数です。 +これは大きなストリームや無限ストリームではさらに重要になります。 - このようにすることで `with` ブロックに入れられ、完了後にfile-likeオブジェクトが確実にクローズされます。 +/// /// tip | 豆知識 -ここでは `async` と `await` をサポートしていない標準の `open()` を使っているため、通常の `def` でpath operationを宣言している点に注意してください。 +`StreamingResponse` を直接返す代わりに、[データをストリームする](./stream-data.md) スタイルに従うことをおすすめします。こちらのほうがはるかに便利で、裏側でキャンセル処理も行ってくれます。 + +JSON Lines をストリームする場合は、[JSON Lines をストリームする](../tutorial/stream-json-lines.md) チュートリアルを参照してください。 /// ### `FileResponse` { #fileresponse } -レスポンスとしてファイルを非同期的にストリームします。 +ファイルをレスポンスとして非同期にストリームします。 -他のレスポンスタイプとは異なる引数のセットを受け取りインスタンス化します。 +他のレスポンスタイプとは異なる引数セットでインスタンス化します: -* `path` - ストリームするファイルのファイルパス。 -* `headers` - 含めたい任意のカスタムヘッダーの辞書。 -* `media_type` - メディアタイプを示す文字列。未設定の場合、ファイル名やパスからメディアタイプが推測されます。 -* `filename` - 設定した場合、レスポンスの `Content-Disposition` に含まれます。 +* `path` - ストリームするファイルのファイルパス +* `headers` - 含めたい任意のカスタムヘッダー(辞書) +* `media_type` - メディアタイプを示す文字列。未設定の場合、ファイル名やパスから推測されます +* `filename` - 設定した場合、レスポンスの `Content-Disposition` に含まれます ファイルレスポンスには、適切な `Content-Length`、`Last-Modified`、`ETag` ヘッダーが含まれます。 @@ -261,17 +213,17 @@ HTTPリダイレクトを返します。デフォルトでは307ステータス {* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} -この場合、*path operation*関数からファイルパスを直接返せます。 +この場合、*path operation* 関数からファイルパスを直接返せます。 ## カスタムレスポンスクラス { #custom-response-class } -`Response` を継承した独自のカスタムレスポンスクラスを作成して利用できます。 +`Response` を継承して、独自のカスタムレスポンスクラスを作成し、使用できます。 -例えば、`orjson`を使いたいが、同梱の `ORJSONResponse` クラスで使われていないカスタム設定も使いたいとします。 +例えば、[`orjson`](https://github.com/ijl/orjson) を特定の設定で使いたいとします。 -例えば、インデントされ整形されたJSONを返したいので、orjsonオプション `orjson.OPT_INDENT_2` を使いたいとします。 +インデントされた整形済みJSONを返したいので、orjson のオプション `orjson.OPT_INDENT_2` を使いたいとします。 -`CustomORJSONResponse` を作れます。主に必要なのは、コンテンツを `bytes` として返す `Response.render(content)` メソッドを作ることです: +`CustomORJSONResponse` を作成できます。主に必要なのは、`bytes` を返す `Response.render(content)` メソッドを作ることです: {* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} @@ -289,24 +241,32 @@ HTTPリダイレクトを返します。デフォルトでは307ステータス } ``` -もちろん、JSONの整形よりも、これを活用するもっと良い方法が見つかるはずです。 😉 +もちろん、JSONの整形以外にも、これを活用するもっと良い方法が見つかるはずです。 😉 + +### `orjson` か レスポンスモデルか { #orjson-or-response-model } + +もし求めているのがパフォーマンスであれば、`orjson` レスポンスを使うより、[レスポンスモデル](../tutorial/response-model.md) を使うほうが良い場合が多いです。 + +レスポンスモデルがあると、FastAPI は中間ステップ(他の場合に行われる `jsonable_encoder` による変換など)を介さずに、Pydantic を使ってデータをJSONにシリアライズします。 + +内部的には、Pydantic はJSONシリアライズに `orjson` と同じRust由来の仕組みを用いているため、レスポンスモデルを使うだけで最良のパフォーマンスが得られます。 ## デフォルトレスポンスクラス { #default-response-class } -**FastAPI** クラスのインスタンス、または `APIRouter` を作成する際に、デフォルトで使用するレスポンスクラスを指定できます。 +**FastAPI** クラスのインスタンスや `APIRouter` を作成する際に、デフォルトで使用するレスポンスクラスを指定できます。 これを定義するパラメータは `default_response_class` です。 -以下の例では、**FastAPI** はすべての*path operation*で、`JSONResponse` の代わりに `ORJSONResponse` をデフォルトとして使います。 +以下の例では、**FastAPI** はすべての *path operation* で、JSONの代わりにデフォルトで `HTMLResponse` を使用します。 {* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} /// tip | 豆知識 -これまでと同様に、*path operation*で `response_class` をオーバーライドできます。 +これまでと同様に、*path operation* ごとに `response_class` をオーバーライドできます。 /// ## その他のドキュメント { #additional-documentation } -OpenAPIでは `responses` を使ってメディアタイプやその他の詳細を宣言することもできます: [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}。 +OpenAPIでは `responses` を使ってメディアタイプやその他の詳細を宣言することもできます: [OpenAPI の追加レスポンス](additional-responses.md)。 diff --git a/docs/ja/docs/advanced/dataclasses.md b/docs/ja/docs/advanced/dataclasses.md index 74f479f072..e3ad7afb63 100644 --- a/docs/ja/docs/advanced/dataclasses.md +++ b/docs/ja/docs/advanced/dataclasses.md @@ -2,11 +2,11 @@ FastAPI は **Pydantic** の上に構築されており、これまでにリクエストやレスポンスを宣言するために Pydantic モデルを使う方法を紹介してきました。 -しかし FastAPI は、同様の方法で `dataclasses` もサポートします: +しかし FastAPI は、同様の方法で [`dataclasses`](https://docs.python.org/3/library/dataclasses.html) もサポートします: {* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} -これは **Pydantic** によって引き続きサポートされています。Pydantic には `dataclasses` の内部サポート があるためです。 +これは **Pydantic** によって引き続きサポートされています。Pydantic には [`dataclasses` の内部サポート](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel) があるためです。 そのため、上記のように明示的に Pydantic を使っていないコードでも、FastAPI は標準の dataclass を Pydantic 独自の dataclass に変換するために Pydantic を使用しています。 @@ -74,7 +74,7 @@ dataclass は自動的に Pydantic の dataclass に変換されます。 いつもどおり、FastAPI では必要に応じて `def` と `async def` を組み合わせられます。 - どちらをいつ使うかの復習が必要な場合は、[`async` と `await`](../async.md#in-a-hurry){.internal-link target=_blank} に関するドキュメントの _"In a hurry?"_ セクションを参照してください。 + どちらをいつ使うかの復習が必要な場合は、[`async` と `await`](../async.md#in-a-hurry) に関するドキュメントの _"In a hurry?"_ セクションを参照してください。 9. この *path operation 関数* は(可能ではありますが)dataclass 自体は返さず、内部データを持つ辞書のリストを返しています。 @@ -88,7 +88,7 @@ dataclass は自動的に Pydantic の dataclass に変換されます。 `dataclasses` を他の Pydantic モデルと組み合わせたり、継承したり、自分のモデルに含めたりもできます。 -詳しくは、dataclasses に関する Pydantic ドキュメント を参照してください。 +詳しくは、[dataclasses に関する Pydantic ドキュメント](https://docs.pydantic.dev/latest/concepts/dataclasses/) を参照してください。 ## バージョン { #version } diff --git a/docs/ja/docs/advanced/events.md b/docs/ja/docs/advanced/events.md index fb79062fa8..e2cbe2eb04 100644 --- a/docs/ja/docs/advanced/events.md +++ b/docs/ja/docs/advanced/events.md @@ -150,11 +150,11 @@ async with lifespan(app): 技術が気になる方への細かな詳細です。🤓 -内部的には、ASGI の技術仕様において、これは Lifespan プロトコル の一部であり、`startup` と `shutdown` というイベントが定義されています。 +内部的には、ASGI の技術仕様において、これは [Lifespan プロトコル](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) の一部であり、`startup` と `shutdown` というイベントが定義されています。 /// info | 情報 -Starlette の `lifespan` ハンドラについては、Starlette の Lifespan ドキュメントで詳しく読むことができます。 +Starlette の `lifespan` ハンドラについては、[Starlette の Lifespan ドキュメント](https://www.starlette.dev/lifespan/)で詳しく読むことができます。 コードの他の領域で使える lifespan の状態をどのように扱うかも含まれています。 @@ -162,4 +162,4 @@ Starlette の `lifespan` ハンドラについては、OpenAPI Generator があります。これは**多数のプログラミング言語**をサポートし、OpenAPI 仕様から SDK を生成できます。 +多用途な選択肢として [OpenAPI Generator](https://openapi-generator.tech/) があります。これは**多数のプログラミング言語**をサポートし、OpenAPI 仕様から SDK を生成できます。 -**TypeScript クライアント**向けには、Hey API が目的特化のソリューションで、TypeScript エコシステムに最適化された体験を提供します。 +**TypeScript クライアント**向けには、[Hey API](https://heyapi.dev/) が目的特化のソリューションで、TypeScript エコシステムに最適化された体験を提供します。 -他の SDK ジェネレータは OpenAPI.Tools でも見つけられます。 +他の SDK ジェネレータは [OpenAPI.Tools](https://openapi.tools/#sdk) でも見つけられます。 /// tip | 豆知識 @@ -24,15 +24,15 @@ FastAPI は自動的に **OpenAPI 3.1** の仕様を生成します。したが このセクションでは、FastAPI をスポンサーしている企業による、**ベンチャー支援**および**企業支援**のソリューションを紹介します。これらの製品は、高品質な生成 SDK に加えて、**追加機能**や**統合**を提供します。 -✨ [**FastAPI をスポンサーする**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨ ことで、これらの企業はフレームワークとその**エコシステム**の健全性と**持続可能性**を支援しています。 +✨ [**FastAPI をスポンサーする**](../help-fastapi.md#sponsor-the-author) ✨ ことで、これらの企業はフレームワークとその**エコシステム**の健全性と**持続可能性**を支援しています。 この支援は、FastAPI の**コミュニティ**(皆さん)への強いコミットメントの表明でもあり、**優れたサービス**の提供だけでなく、堅牢で発展するフレームワーク FastAPI を支える姿勢を示しています。🙇 例えば、次のようなものがあります: -* Speakeasy -* Stainless -* liblab +* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) +* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) +* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) これらのソリューションの中にはオープンソースや無料枠を提供するものもあり、金銭的コミットメントなしで試すことができます。他の商用 SDK ジェネレータも存在し、オンラインで見つけられます。🤓 @@ -66,7 +66,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client これで TypeScript SDK が `./src/client` に生成されます。 -`@hey-api/openapi-ts` のインストール方法や、生成物の詳細は公式サイトを参照してください。 +[`@hey-api/openapi-ts` のインストール方法](https://heyapi.dev/openapi-ts/get-started)や、[生成物の詳細](https://heyapi.dev/openapi-ts/output)は公式サイトを参照してください。 ### SDK の利用 { #using-the-sdk } diff --git a/docs/ja/docs/advanced/index.md b/docs/ja/docs/advanced/index.md index 1d0f7566cd..026405318f 100644 --- a/docs/ja/docs/advanced/index.md +++ b/docs/ja/docs/advanced/index.md @@ -2,7 +2,7 @@ ## さらなる機能 { #additional-features } -メインの[チュートリアル - ユーザーガイド](../tutorial/index.md){.internal-link target=_blank}だけで、**FastAPI**の主要な機能を一通り把握するには十分なはずです。 +メインの[チュートリアル - ユーザーガイド](../tutorial/index.md)だけで、**FastAPI**の主要な機能を一通り把握するには十分なはずです。 以降のセクションでは、その他のオプション、設定、追加機能を見ていきます。 @@ -16,6 +16,6 @@ ## 先にチュートリアルを読む { #read-the-tutorial-first } -メインの[チュートリアル - ユーザーガイド](../tutorial/index.md){.internal-link target=_blank}で得た知識があれば、**FastAPI**の機能の多くは引き続き利用できます。 +メインの[チュートリアル - ユーザーガイド](../tutorial/index.md)で得た知識があれば、**FastAPI**の機能の多くは引き続き利用できます。 また、以降のセクションでは、すでにそれを読んでいて、主要な考え方を理解していることを前提としています。 diff --git a/docs/ja/docs/advanced/middleware.md b/docs/ja/docs/advanced/middleware.md index 2883d53d82..018e660588 100644 --- a/docs/ja/docs/advanced/middleware.md +++ b/docs/ja/docs/advanced/middleware.md @@ -1,8 +1,8 @@ # 高度なミドルウェア { #advanced-middleware } -メインのチュートリアルでは、アプリケーションに[カスタムミドルウェア](../tutorial/middleware.md){.internal-link target=_blank}を追加する方法を学びました。 +メインのチュートリアルでは、アプリケーションに[カスタムミドルウェア](../tutorial/middleware.md)を追加する方法を学びました。 -そして、[`CORSMiddleware` を使った CORS の扱い方](../tutorial/cors.md){.internal-link target=_blank}も学びました。 +そして、[`CORSMiddleware` を使った CORS の扱い方](../tutorial/cors.md)も学びました。 このセクションでは、その他のミドルウェアの使い方を見ていきます。 @@ -91,7 +91,7 @@ HTTP Host Header 攻撃を防ぐため、すべての受信リクエストに正 例えば: -- Uvicorn の `ProxyHeadersMiddleware` -- MessagePack +- [Uvicorn の `ProxyHeadersMiddleware`](https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py) +- [MessagePack](https://github.com/florimondmanca/msgpack-asgi) -他に利用可能なミドルウェアについては、Starlette のミドルウェアドキュメントASGI Awesome List を参照してください。 +他に利用可能なミドルウェアについては、[Starlette のミドルウェアドキュメント](https://www.starlette.dev/middleware/)や [ASGI Awesome List](https://github.com/florimondmanca/awesome-asgi) を参照してください。 diff --git a/docs/ja/docs/advanced/openapi-callbacks.md b/docs/ja/docs/advanced/openapi-callbacks.md index 283a80b210..31d17e270b 100644 --- a/docs/ja/docs/advanced/openapi-callbacks.md +++ b/docs/ja/docs/advanced/openapi-callbacks.md @@ -35,7 +35,7 @@ /// tip | 豆知識 -`callback_url` クエリパラメータは、Pydantic の Url 型を使用します。 +`callback_url` クエリパラメータは、Pydantic の [Url](https://docs.pydantic.dev/latest/api/networks/) 型を使用します。 /// @@ -66,7 +66,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) 実際のコールバックは単なる HTTP リクエストです。 -自分でコールバックを実装する場合は、HTTPXRequests のようなものを使えます。 +自分でコールバックを実装する場合は、[HTTPX](https://www.python-httpx.org) や [Requests](https://requests.readthedocs.io/) のようなものを使えます。 /// @@ -106,11 +106,11 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) 通常の *path operation* と異なる主な点が 2 つあります: * 実際のコードは不要です。あなたのアプリはこのコードを決して呼びません。これは *外部 API* をドキュメント化するためだけに使われます。したがって、関数本体は `pass` で構いません。 -* *パス* には、*あなたの API* に送られた元のリクエストのパラメータや一部を変数として使える OpenAPI 3 の式(後述)を含められます。 +* *パス* には、*あなたの API* に送られた元のリクエストのパラメータや一部を変数として使える [OpenAPI 3 の式](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)(後述)を含められます。 ### コールバックのパス式 { #the-callback-path-expression } -コールバックの *パス* には、*あなたの API* に送られた元のリクエストの一部を含められる OpenAPI 3 の式を使用できます。 +コールバックの *パス* には、*あなたの API* に送られた元のリクエストの一部を含められる [OpenAPI 3 の式](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)を使用できます。 この例では、`str` は次のとおりです: @@ -179,7 +179,7 @@ JSON ボディは次のような内容です: ### ドキュメントを確認 { #check-the-docs } -アプリを起動して http://127.0.0.1:8000/docs にアクセスします。 +アプリを起動して [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) にアクセスします。 あなたの *path operation* に「Callbacks」セクションが含まれ、*外部 API* がどうあるべきかが表示されているのが確認できます: diff --git a/docs/ja/docs/advanced/openapi-webhooks.md b/docs/ja/docs/advanced/openapi-webhooks.md index 368cfddd82..7f7a726807 100644 --- a/docs/ja/docs/advanced/openapi-webhooks.md +++ b/docs/ja/docs/advanced/openapi-webhooks.md @@ -48,7 +48,7 @@ Webhook では(`/items/` のような)*パス*を宣言しているわけで ### ドキュメントの確認 { #check-the-docs } -アプリを起動し、http://127.0.0.1:8000/docs にアクセスします。 +アプリを起動し、[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) にアクセスします。 ドキュメントには通常の *path operations* に加えて、**webhooks** も表示されます: diff --git a/docs/ja/docs/advanced/path-operation-advanced-configuration.md b/docs/ja/docs/advanced/path-operation-advanced-configuration.md index f7e3406171..65b56dba4c 100644 --- a/docs/ja/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/ja/docs/advanced/path-operation-advanced-configuration.md @@ -60,7 +60,7 @@ APIの関数名を `operationId` として利用したい場合、すべてのAP 追加のレスポンスについても、モデルやステータスコードなどとともに宣言できます。 -これについてはドキュメントに章全体があります。 [OpenAPIの追加レスポンス](additional-responses.md){.internal-link target=_blank} で読めます。 +これについてはドキュメントに章全体があります。 [OpenAPIの追加レスポンス](additional-responses.md) で読めます。 ## OpenAPI Extra { #openapi-extra } @@ -68,7 +68,7 @@ APIの関数名を `operationId` として利用したい場合、すべてのAP /// note | 技術詳細 -OpenAPI仕様では Operation Object と呼ばれています。 +OpenAPI仕様では [Operation Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object) と呼ばれています。 /// @@ -82,7 +82,7 @@ OpenAPI仕様では Starlette のドキュメントを参照してください。 +利用可能なすべてのパラメータやオプションについては、[Starlette のドキュメント](https://www.starlette.dev/responses/#set-cookie)を参照してください。 diff --git a/docs/ja/docs/advanced/response-directly.md b/docs/ja/docs/advanced/response-directly.md index 103e84c385..b5c9fc5cbf 100644 --- a/docs/ja/docs/advanced/response-directly.md +++ b/docs/ja/docs/advanced/response-directly.md @@ -1,22 +1,26 @@ # レスポンスを直接返す { #return-a-response-directly } -**FastAPI** の *path operation* では、通常は任意のデータを返すことができます: 例えば、 `dict`、`list`、Pydanticモデル、データベースモデルなどです。 +**FastAPI** の *path operation* では、通常は任意のデータを返すことができます: 例えば、`dict`、`list`、Pydanticモデル、データベースモデルなどです。 -デフォルトでは、**FastAPI** は [JSON互換エンコーダ](../tutorial/encoder.md){.internal-link target=_blank} で説明されている `jsonable_encoder` により、返す値を自動的にJSONに変換します。 +[レスポンスモデル](../tutorial/response-model.md) を宣言した場合、FastAPI は Pydantic を使ってデータをJSONにシリアライズします。 -このとき背後では、JSON互換なデータ (例えば`dict`) を、クライアントへ送信されるレスポンスとして利用される `JSONResponse` の中に含めます。 +レスポンスモデルを宣言しない場合、FastAPI は [JSON互換エンコーダ](../tutorial/encoder.md) で説明されている `jsonable_encoder` を使用し、その結果を `JSONResponse` に入れます。 -しかし、*path operation* から `JSONResponse` を直接返すこともできます。 +また、`JSONResponse` を直接作成して返すこともできます。 -これは例えば、カスタムヘッダーやcookieを返すときに便利です。 +/// tip + +通常は、`JSONResponse` を直接返すよりも、[レスポンスモデル](../tutorial/response-model.md) を使うほうがパフォーマンスが大幅に良くなります。これは、Pydantic によるシリアライズが Rust で実行されるためです。 + +/// ## `Response` を返す { #return-a-response } 実際は、`Response` やそのサブクラスを返すことができます。 -/// tip | 豆知識 +/// info -`JSONResponse` それ自体は、 `Response` のサブクラスです。 +`JSONResponse` それ自体は、`Response` のサブクラスです。 /// @@ -26,6 +30,8 @@ これは多くの柔軟性を提供します。任意のデータ型を返したり、任意のデータ宣言やバリデーションをオーバーライドできます。 +同時に多くの責任も伴います。返すデータが正しく、正しいフォーマットであり、シリアライズ可能であることなどを、あなたが保証しなければなりません。 + ## `jsonable_encoder` を `Response` の中で使う { #using-the-jsonable-encoder-in-a-response } **FastAPI** はあなたが返す `Response` に対して何も変更を加えないので、コンテンツが準備できていることを保証しなければなりません。 @@ -46,20 +52,32 @@ ## カスタム `Response` を返す { #returning-a-custom-response } -上記の例では必要な部分を全て示していますが、あまり便利ではありません。`item` を直接返すことができるし、**FastAPI** はそれを `dict` に変換して `JSONResponse` に含めてくれるなど。すべて、デフォルトの動作です。 +上記の例では必要な部分を全て示していますが、あまり便利ではありません。`item` を直接返すことができるし、**FastAPI** はそれを `dict` に変換して `JSONResponse` に含めてくれるなど。すべて、デフォルトの動作です。 では、これを使ってカスタムレスポンスをどう返すか見てみましょう。 -XMLレスポンスを返したいとしましょう。 +[XML](https://en.wikipedia.org/wiki/XML)レスポンスを返したいとしましょう。 XMLを文字列にし、`Response` に含め、それを返します。 {* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} +## Response Model の仕組み { #how-a-response-model-works } + +path operation で [Response Model - 戻り値の型](../tutorial/response-model.md) を宣言すると、**FastAPI** はそれを使って Pydantic によりデータをJSONにシリアライズします。 + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +これは Rust 側で行われるため、通常の Python と `JSONResponse` クラスで行う場合より、パフォーマンスははるかに良くなります。 + +`response_model` や戻り値の型を使用する場合、FastAPI はデータ変換に(低速になりうる)`jsonable_encoder` も `JSONResponse` クラスも使いません。 + +代わりに、response model(または戻り値の型)を使って Pydantic が生成した JSON のバイト列をそのまま用い、JSON 用の正しいメディアタイプ(`application/json`)を持つ `Response` を直接返します。 + ## 備考 { #notes } `Response` を直接返す場合、バリデーションや、変換 (シリアライズ) や、自動ドキュメントは行われません。 -しかし、[Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}に記載されたようにドキュメントを書くこともできます。 +しかし、[Additional Responses in OpenAPI](additional-responses.md)に記載されたようにドキュメントを書くこともできます。 後のセクションで、カスタム `Response` を使用・宣言しながら、自動的なデータ変換やドキュメンテーションを行う方法を説明します。 diff --git a/docs/ja/docs/advanced/response-headers.md b/docs/ja/docs/advanced/response-headers.md index 10aec78452..3a61f57428 100644 --- a/docs/ja/docs/advanced/response-headers.md +++ b/docs/ja/docs/advanced/response-headers.md @@ -20,7 +20,7 @@ `Response` を直接返す場合にもヘッダーを追加できます。 -[Response を直接返す](response-directly.md){.internal-link target=_blank} で説明したようにレスポンスを作成し、ヘッダーを追加のパラメータとして渡します: +[Response を直接返す](response-directly.md) で説明したようにレスポンスを作成し、ヘッダーを追加のパラメータとして渡します: {* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} @@ -36,6 +36,6 @@ ## カスタムヘッダー { #custom-headers } -独自のカスタムヘッダーは、`X-` プレフィックスを使って追加できることに注意してください。 +独自のカスタムヘッダーは、[`X-` プレフィックスを使って](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)追加できることに注意してください。 -ただし、ブラウザのクライアントに見えるようにしたいカスタムヘッダーがある場合は、CORS 設定にそれらを追加する必要があります([CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank} を参照)。このとき、Starlette の CORS ドキュメントに記載の `expose_headers` パラメータを使用します。 +ただし、ブラウザのクライアントに見えるようにしたいカスタムヘッダーがある場合は、CORS 設定にそれらを追加する必要があります([CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md) を参照)。このとき、[Starlette の CORS ドキュメント](https://www.starlette.dev/middleware/#corsmiddleware)に記載の `expose_headers` パラメータを使用します。 diff --git a/docs/ja/docs/advanced/security/http-basic-auth.md b/docs/ja/docs/advanced/security/http-basic-auth.md index 7ee56a039b..b8e47dcbb7 100644 --- a/docs/ja/docs/advanced/security/http-basic-auth.md +++ b/docs/ja/docs/advanced/security/http-basic-auth.md @@ -32,7 +32,7 @@ URL を最初に開こうとしたとき(またはドキュメントで「Exec 依存関係を使ってユーザー名とパスワードが正しいかを確認します。 -これには、Python 標準モジュール `secrets` を用いてユーザー名とパスワードを検証します。 +これには、Python 標準モジュール [`secrets`](https://docs.python.org/3/library/secrets.html) を用いてユーザー名とパスワードを検証します。 `secrets.compare_digest()` は `bytes` か、ASCII 文字(英語の文字)のみを含む `str` を受け取る必要があります。つまり、`Sebastián` のように `á` を含む文字ではそのままでは動作しません。 @@ -46,7 +46,7 @@ URL を最初に開こうとしたとき(またはドキュメントで「Exec ```Python if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"): - # Return some error + # 何らかのエラーを返す ... ``` diff --git a/docs/ja/docs/advanced/security/index.md b/docs/ja/docs/advanced/security/index.md index 069e2686cb..5b4c480fe9 100644 --- a/docs/ja/docs/advanced/security/index.md +++ b/docs/ja/docs/advanced/security/index.md @@ -2,11 +2,11 @@ ## 追加機能 { #additional-features } -[チュートリアル - ユーザーガイド: セキュリティ](../../tutorial/security/index.md){.internal-link target=_blank}で扱ったもの以外にも、セキュリティを扱うための追加機能がいくつかあります。 +[チュートリアル - ユーザーガイド: セキュリティ](../../tutorial/security/index.md)で扱ったもの以外にも、セキュリティを扱うための追加機能がいくつかあります。 /// tip | 豆知識 -次の節は必ずしも「高度」ではありません。 +次の節は**必ずしも「高度」ではありません**。 あなたのユースケースでは、その中のいずれかに解決策があるかもしれません。 @@ -14,6 +14,6 @@ ## まずチュートリアルを読む { #read-the-tutorial-first } -以下の節は、すでにメインの[チュートリアル - ユーザーガイド: セキュリティ](../../tutorial/security/index.md){.internal-link target=_blank}を読んでいることを前提とします。 +以下の節は、すでにメインの[チュートリアル - ユーザーガイド: セキュリティ](../../tutorial/security/index.md)を読んでいることを前提とします。 いずれも同じ概念に基づいていますが、いくつかの追加機能を利用できます。 diff --git a/docs/ja/docs/advanced/security/oauth2-scopes.md b/docs/ja/docs/advanced/security/oauth2-scopes.md index 7c6cfdbf03..3afc26e3ae 100644 --- a/docs/ja/docs/advanced/security/oauth2-scopes.md +++ b/docs/ja/docs/advanced/security/oauth2-scopes.md @@ -60,7 +60,7 @@ OAuth2 にとっては、単に文字列に過ぎません。 ## 全体像 { #global-view } -まず、メインの**チュートリアル - ユーザーガイド**にある [OAuth2(パスワード[ハッシュ化あり])、Bearer と JWT トークン](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank} の例から変更される部分を、スコープ付き OAuth2 を使って手早く見てみましょう。 +まず、メインの**チュートリアル - ユーザーガイド**にある [OAuth2(パスワード[ハッシュ化あり])、Bearer と JWT トークン](../../tutorial/security/oauth2-jwt.md) の例から変更される部分を、スコープ付き OAuth2 を使って手早く見てみましょう。 {* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} @@ -271,4 +271,4 @@ API ドキュメントを開くと、認証して、許可するスコープを ## デコレータ `dependencies` での `Security` { #security-in-decorator-dependencies } -デコレータの `dependencies` パラメータに `Depends` の `list` を定義できるのと同様([path operation デコレータでの依存関係](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} 参照)、ここで `scopes` を指定した `Security` も使用できます。 +デコレータの `dependencies` パラメータに `Depends` の `list` を定義できるのと同様([path operation デコレータでの依存関係](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md) 参照)、ここで `scopes` を指定した `Security` も使用できます。 diff --git a/docs/ja/docs/advanced/settings.md b/docs/ja/docs/advanced/settings.md index 5508ad6d91..e42ec845c6 100644 --- a/docs/ja/docs/advanced/settings.md +++ b/docs/ja/docs/advanced/settings.md @@ -8,7 +8,7 @@ /// tip | 豆知識 -環境変数について理解するには、[環境変数](../environment-variables.md){.internal-link target=_blank}を参照してください。 +環境変数について理解するには、[環境変数](../environment-variables.md)を参照してください。 /// @@ -20,11 +20,11 @@ ## Pydantic の `Settings` { #pydantic-settings } -幸いなことに、Pydantic には環境変数から来る設定を扱うための優れたユーティリティがあり、Pydantic: Settings management で提供されています。 +幸いなことに、Pydantic には環境変数から来る設定を扱うための優れたユーティリティがあり、[Pydantic: Settings management](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) で提供されています。 ### `pydantic-settings` のインストール { #install-pydantic-settings } -まず、[仮想環境](../virtual-environments.md){.internal-link target=_blank}を作成して有効化し、`pydantic-settings` パッケージをインストールします: +まず、[仮想環境](../virtual-environments.md)を作成して有効化し、`pydantic-settings` パッケージをインストールします:
@@ -100,7 +100,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p ## 別モジュールでの設定 { #settings-in-another-module } -[大規模アプリケーション - 複数ファイル](../tutorial/bigger-applications.md){.internal-link target=_blank} で見たように、これらの設定を別のモジュールファイルに置くこともできます。 +[大規模アプリケーション - 複数ファイル](../tutorial/bigger-applications.md) で見たように、これらの設定を別のモジュールファイルに置くこともできます。 たとえば、`config.py` というファイルに次のように書けます: @@ -112,7 +112,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p /// tip | 豆知識 -[大規模アプリケーション - 複数ファイル](../tutorial/bigger-applications.md){.internal-link target=_blank} で見たように、`__init__.py` ファイルも必要です。 +[大規模アプリケーション - 複数ファイル](../tutorial/bigger-applications.md) で見たように、`__init__.py` ファイルも必要です。 /// @@ -172,7 +172,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p /// -Pydantic は外部ライブラリを使ってこの種のファイルからの読み込みをサポートしています。詳細は Pydantic Settings: Dotenv (.env) support を参照してください。 +Pydantic は外部ライブラリを使ってこの種のファイルからの読み込みをサポートしています。詳細は [Pydantic Settings: Dotenv (.env) support](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support) を参照してください。 /// tip | 豆知識 @@ -197,7 +197,7 @@ APP_NAME="ChimichangApp" /// tip | 豆知識 -`model_config` 属性は Pydantic の設定専用です。詳しくは Pydantic: Concepts: Configuration を参照してください。 +`model_config` 属性は Pydantic の設定専用です。詳しくは [Pydantic: Concepts: Configuration](https://docs.pydantic.dev/latest/concepts/config/) を参照してください。 /// @@ -291,7 +291,7 @@ participant execute as Execute function この方法は、ほとんどグローバル変数のように振る舞います。しかし、依存関数を使っているので、テストのために簡単にオーバーライドできます。 -`@lru_cache` は Python 標準ライブラリの `functools` の一部です。詳細は Python の `@lru_cache` ドキュメントを参照してください。 +`@lru_cache` は Python 標準ライブラリの `functools` の一部です。詳細は [Python の `@lru_cache` ドキュメント](https://docs.python.org/3/library/functools.html#functools.lru_cache)を参照してください。 ## まとめ { #recap } diff --git a/docs/ja/docs/advanced/sub-applications.md b/docs/ja/docs/advanced/sub-applications.md index f38da1423e..e9b17031b5 100644 --- a/docs/ja/docs/advanced/sub-applications.md +++ b/docs/ja/docs/advanced/sub-applications.md @@ -30,25 +30,25 @@ ### 自動 API ドキュメントの確認 { #check-the-automatic-api-docs } -では、`fastapi` コマンドでこのファイルを実行します: +では、`fastapi` コマンドを実行します:
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-そして、http://127.0.0.1:8000/docs を開きます。 +そして、[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) を開きます。 メインアプリ用の自動 API ドキュメントが表示され、そのアプリ自身の path operation のみが含まれます: -次に、サブアプリケーションのドキュメント http://127.0.0.1:8000/subapi/docs を開きます。 +次に、サブアプリケーションのドキュメント [http://127.0.0.1:8000/subapi/docs](http://127.0.0.1:8000/subapi/docs) を開きます。 サブアプリケーション用の自動 API ドキュメントが表示され、そのアプリ自身の path operation のみが、正しいサブパス接頭辞 `/subapi` の下で表示されます: @@ -64,4 +64,4 @@ $ fastapi dev main.py さらに、サブアプリケーション自身が別のサブアプリケーションをマウントしていても問題ありません。FastAPI がこれらの `root_path` をすべて自動的に処理するためです。 -`root_path` の詳細や明示的な指定方法については、[プロキシの背後で](behind-a-proxy.md){.internal-link target=_blank} の節で学べます。 +`root_path` の詳細や明示的な指定方法については、[プロキシの背後で](behind-a-proxy.md) の節で学べます。 diff --git a/docs/ja/docs/advanced/templates.md b/docs/ja/docs/advanced/templates.md index 3c4827b88e..5495b73a0b 100644 --- a/docs/ja/docs/advanced/templates.md +++ b/docs/ja/docs/advanced/templates.md @@ -8,7 +8,7 @@ Starlette によって提供され、**FastAPI** アプリで直接使える、 ## 依存関係のインストール { #install-dependencies } -[仮想環境](../virtual-environments.md){.internal-link target=_blank} を作成して有効化し、`jinja2` をインストールします: +[仮想環境](../virtual-environments.md) を作成して有効化し、`jinja2` をインストールします:
@@ -123,4 +123,4 @@ Item ID: 42 ## さらに詳しく { #more-details } -より詳しい内容(テンプレートのテスト方法など)については、Starlette のテンプレートに関するドキュメントを参照してください。 +より詳しい内容(テンプレートのテスト方法など)については、[Starlette のテンプレートに関するドキュメント](https://www.starlette.dev/templates/)を参照してください。 diff --git a/docs/ja/docs/advanced/testing-websockets.md b/docs/ja/docs/advanced/testing-websockets.md index 7f708ea1a2..745e636087 100644 --- a/docs/ja/docs/advanced/testing-websockets.md +++ b/docs/ja/docs/advanced/testing-websockets.md @@ -8,6 +8,6 @@ WebSocket をテストするのにも同じ `TestClient` を使用できます /// note | 備考 -詳細については、Starlette のドキュメント「WebSocket のテスト」を参照してください。 +詳細については、Starlette のドキュメント「[WebSocket のテスト](https://www.starlette.dev/testclient/#testing-websocket-sessions)」を参照してください。 /// diff --git a/docs/ja/docs/advanced/using-request-directly.md b/docs/ja/docs/advanced/using-request-directly.md index 1e564f5945..59d7290e67 100644 --- a/docs/ja/docs/advanced/using-request-directly.md +++ b/docs/ja/docs/advanced/using-request-directly.md @@ -15,7 +15,7 @@ ## `Request` オブジェクトの詳細 { #details-about-the-request-object } -**FastAPI** は内部的には **Starlette** の上にいくつかのツール層を載せたものなので、必要に応じて Starlette の `Request` オブジェクトを直接使えます。 +**FastAPI** は内部的には **Starlette** の上にいくつかのツール層を載せたものなので、必要に応じて Starlette の [`Request`](https://www.starlette.dev/requests/) オブジェクトを直接使えます。 また、`Request` オブジェクトから直接データ(例: ボディ)を取得する場合、そのデータは FastAPI によって検証・変換・ドキュメント化(OpenAPI による自動 API ユーザーインターフェース向け)されません。 @@ -45,7 +45,7 @@ path operation 関数の引数として `Request` 型のパラメータを宣言 ## `Request` のドキュメント { #request-documentation } -より詳しくは、公式 Starlette ドキュメントサイトの `Request` オブジェクトを参照してください。 +より詳しくは、[公式 Starlette ドキュメントサイトの `Request` オブジェクト](https://www.starlette.dev/requests/)を参照してください。 /// note | 技術詳細 diff --git a/docs/ja/docs/advanced/websockets.md b/docs/ja/docs/advanced/websockets.md index efc02079bb..802110b587 100644 --- a/docs/ja/docs/advanced/websockets.md +++ b/docs/ja/docs/advanced/websockets.md @@ -1,10 +1,10 @@ # WebSockets { #websockets } -**FastAPI**でWebSocketsが使用できます。 +**FastAPI**で[WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)が使用できます。 ## `websockets`のインストール { #install-websockets } -[仮想環境](../virtual-environments.md){.internal-link target=_blank}を作成し、それを有効化してから、「WebSocket」プロトコルを簡単に使えるようにするPythonライブラリの`websockets`をインストールしてください。 +[仮想環境](../virtual-environments.md)を作成し、それを有効化してから、「WebSocket」プロトコルを簡単に使えるようにするPythonライブラリの`websockets`をインストールしてください。
@@ -64,19 +64,19 @@ WebSocketルートでは、メッセージを待機して送信するために ` ## 試してみる { #try-it } -ファイル名が `main.py` である場合、以下でアプリケーションを実行します。 +コードを `main.py` に入れて、アプリケーションを実行します。
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-ブラウザで http://127.0.0.1:8000 を開きます。 +ブラウザで [http://127.0.0.1:8000](http://127.0.0.1:8000) を開きます。 次のようなシンプルなページが表示されます。 @@ -115,25 +115,25 @@ WebSocketエンドポイントでは、`fastapi` から以下をインポート これはWebSocketであるため、`HTTPException` を発生させることはあまり意味がありません。代わりに `WebSocketException` を発生させます。 -クロージングコードは、仕様で定義された有効なコードの中から使用することができます。 +クロージングコードは、[仕様で定義された有効なコード](https://tools.ietf.org/html/rfc6455#section-7.4.1)の中から使用することができます。 /// ### 依存関係を用いてWebSocketsを試してみる { #try-the-websockets-with-dependencies } -ファイル名が `main.py` である場合、以下でアプリケーションを実行します。 +アプリケーションを実行します。
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-ブラウザで http://127.0.0.1:8000 を開きます。 +ブラウザで [http://127.0.0.1:8000](http://127.0.0.1:8000) を開きます。 そこで、以下を設定できます。 @@ -174,7 +174,7 @@ Client #1596980209979 left the chat しかし、すべてがメモリ内の単一のリストで処理されるため、プロセスの実行中にのみ機能し、単一のプロセスでのみ機能することに注意してください。 -FastAPIと簡単に統合できて、RedisやPostgreSQLなどでサポートされている、より堅牢なものが必要なら、encode/broadcaster を確認してください。 +FastAPIと簡単に統合できて、RedisやPostgreSQLなどでサポートされている、より堅牢なものが必要なら、[encode/broadcaster](https://github.com/encode/broadcaster) を確認してください。 /// @@ -182,5 +182,5 @@ FastAPIと簡単に統合できて、RedisやPostgreSQLなどでサポートさ オプションの詳細については、Starletteのドキュメントを確認してください。 -* `WebSocket` クラス. -* クラスベースのWebSocket処理. +* [`WebSocket` クラス](https://www.starlette.dev/websockets/)。 +* [クラスベースのWebSocket処理](https://www.starlette.dev/endpoints/#websocketendpoint)。 diff --git a/docs/ja/docs/advanced/wsgi.md b/docs/ja/docs/advanced/wsgi.md index b06b4a3299..6895eb6584 100644 --- a/docs/ja/docs/advanced/wsgi.md +++ b/docs/ja/docs/advanced/wsgi.md @@ -1,6 +1,6 @@ # WSGI の組み込み - Flask、Django など { #including-wsgi-flask-django-others } -[サブアプリケーション - マウント](sub-applications.md){.internal-link target=_blank}、[プロキシの背後](behind-a-proxy.md){.internal-link target=_blank} で見たように、WSGI アプリケーションをマウントできます。 +[サブアプリケーション - マウント](sub-applications.md)、[プロキシの背後](behind-a-proxy.md) で見たように、WSGI アプリケーションをマウントできます。 そのために `WSGIMiddleware` を使用して、Flask や Django などの WSGI アプリをラップできます。 @@ -36,13 +36,13 @@ それ以外は **FastAPI** が処理します。 -実行して http://localhost:8000/v1/ にアクセスすると、Flask からのレスポンスが表示されます: +実行して [http://localhost:8000/v1/](http://localhost:8000/v1/) にアクセスすると、Flask からのレスポンスが表示されます: ```txt Hello, World from Flask! ``` -さらに http://localhost:8000/v2 にアクセスすると、FastAPI からのレスポンスが表示されます: +さらに [http://localhost:8000/v2](http://localhost:8000/v2) にアクセスすると、FastAPI からのレスポンスが表示されます: ```JSON { diff --git a/docs/ja/docs/alternatives.md b/docs/ja/docs/alternatives.md index 8b1ec072d6..34017b00e9 100644 --- a/docs/ja/docs/alternatives.md +++ b/docs/ja/docs/alternatives.md @@ -14,7 +14,7 @@ ## 以前のツール { #previous-tools } -### Django { #django } +### [Django](https://www.djangoproject.com/) { #django } Pythonのフレームワークの中で最もポピュラーで、広く信頼されています。Instagramのようなシステムの構築に使われています。 @@ -22,7 +22,7 @@ Pythonのフレームワークの中で最もポピュラーで、広く信頼 バックエンドでHTMLを生成するために作られたものであり、現代的なフロントエンド (ReactやVue.js、Angularなど) や、他のシステム (IoTデバイスなど) と通信するAPIを構築するために作られたものではありません。 -### Django REST Framework { #django-rest-framework } +### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } Django REST Frameworkは、Djangoを下敷きにしてWeb APIを構築する柔軟なツールキットとして、APIの機能を向上させるために作られました。 @@ -42,7 +42,7 @@ Django REST Framework は Tom Christie によって作成されました。Starl /// -### Flask { #flask } +### [Flask](https://flask.palletsprojects.com) { #flask } Flask は「マイクロフレームワーク」であり、データベースとの統合のようなDjangoがデフォルトで持つ多くの機能は含まれていません。 @@ -64,7 +64,7 @@ Flaskのシンプルさを考えると、APIを構築するのに適している /// -### Requests { #requests } +### [Requests](https://requests.readthedocs.io) { #requests } **FastAPI**は実際には**Requests**の代替ではありません。それらのスコープは大きく異なります。 @@ -106,7 +106,7 @@ def read_url(): /// -### Swagger / OpenAPI { #swagger-openapi } +### [Swagger](https://swagger.io/) / [OpenAPI](https://github.com/OAI/OpenAPI-Specification/) { #swagger-openapi } 私がDjango REST Frameworkに求めていた主な機能は、APIの自動的なドキュメント生成でした。 @@ -124,8 +124,8 @@ def read_url(): そして、標準に基づくユーザーインターフェースツールを統合しています。 -* Swagger UI -* ReDoc +* [Swagger UI](https://github.com/swagger-api/swagger-ui) +* [ReDoc](https://github.com/Rebilly/ReDoc) この二つは人気で安定したものとして選択されましたが、少し検索してみると、 (**FastAPI**と同時に使用できる) OpenAPIのための多くの代替となるツールを見つけることができます。 @@ -135,7 +135,7 @@ def read_url(): いくつかのFlask RESTフレームワークがありますが、それらを調査してみたところ、多くのものが不適切な問題が残ったまま、中断されたり放置されていることがわかりました。 -### Marshmallow { #marshmallow } +### [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) { #marshmallow } APIシステムで必要とされる主な機能の一つに、コード (Python) からデータを取り出して、ネットワークを介して送れるものに変換するデータの「シリアライゼーション」があります。例えば、データベースのデータを含むオブジェクトをJSONオブジェクトに変換したり、`datetime` オブジェクトを文字列に変換するなどです。 @@ -153,7 +153,7 @@ APIが必要とするもう一つの大きな機能はデータのバリデー /// -### Webargs { #webargs } +### [Webargs](https://webargs.readthedocs.io/en/latest/) { #webargs } APIに求められる他の大きな機能として、受信したリクエストデータのパースがあります。 @@ -175,7 +175,7 @@ Webargsは、Marshmallowと同じ開発者により作られました。 /// -### APISpec { #apispec } +### [APISpec](https://apispec.readthedocs.io/en/stable/) { #apispec } MarshmallowとWebargsはバリデーション、パース、シリアライゼーションをプラグインとして提供しています。 @@ -205,7 +205,7 @@ OpenAPIという、APIについてのオープンな標準をサポートして /// -### Flask-apispec { #flask-apispec } +### [Flask-apispec](https://flask-apispec.readthedocs.io/en/latest/) { #flask-apispec } Webargs、Marshmallow、APISpecを連携させたFlaskプラグインです。 @@ -219,11 +219,11 @@ Flask、Flask-apispec、Marshmallow、Webargsの組み合わせは、**FastAPI** これを使うことで、いくつかのFlaskフルスタックジェネレータを作成することになりました。これらは私 (といくつかの外部のチーム) が今まで使ってきたメインのスタックです。 -* https://github.com/tiangolo/full-stack -* https://github.com/tiangolo/full-stack-flask-couchbase -* https://github.com/tiangolo/full-stack-flask-couchdb +* [https://github.com/tiangolo/full-stack](https://github.com/tiangolo/full-stack) +* [https://github.com/tiangolo/full-stack-flask-couchbase](https://github.com/tiangolo/full-stack-flask-couchbase) +* [https://github.com/tiangolo/full-stack-flask-couchdb](https://github.com/tiangolo/full-stack-flask-couchdb) -そして、これらのフルスタックジェネレーターは、[**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}の元となっていました。 +そして、これらのフルスタックジェネレーターは、[**FastAPI** Project Generators](project-generation.md)の元となっていました。 /// info | 情報 @@ -237,7 +237,7 @@ Flask-apispecはMarshmallowと同じ開発者により作成されました。 /// -### NestJS (とAngular) { #nestjs-and-angular } +### [NestJS](https://nestjs.com/) (と[Angular](https://angular.io/)) { #nestjs-and-angular } NestJSはAngularにインスパイアされたJavaScript (TypeScript) NodeJSフレームワークで、Pythonですらありません。 @@ -259,13 +259,13 @@ Angular 2にインスピレーションを受けた、統合された依存性 /// -### Sanic { #sanic } +### [Sanic](https://sanic.readthedocs.io/en/latest/) { #sanic } `asyncio`に基づいた、Pythonのフレームワークの中でも非常に高速なものの一つです。Flaskと非常に似た作りになっています。 /// note | 技術詳細 -Pythonの`asyncio`ループの代わりに、`uvloop`が利用されています。それにより、非常に高速です。 +Pythonの`asyncio`ループの代わりに、[`uvloop`](https://github.com/MagicStack/uvloop)が利用されています。それにより、非常に高速です。 `Uvicorn`と`Starlette`に明らかなインスピレーションを与えており、それらは現在オープンなベンチマークにおいてSanicより高速です。 @@ -279,7 +279,7 @@ Pythonの`asyncio`ループの代わりに、Falcon { #falcon } +### [Falcon](https://falconframework.org/) { #falcon } Falconはもう一つの高性能Pythonフレームワークで、ミニマムに設計されており、Hugのような他のフレームワークの基盤として動作します。 @@ -297,7 +297,7 @@ Hug (HugはFalconをベースにしています) と一緒に、**FastAPI**が`r /// -### Molten { #molten } +### [Molten](https://moltenframework.com/) { #molten } **FastAPI**を構築する最初の段階でMoltenを発見しました。そして、それは非常に似たようなアイデアを持っています。 @@ -321,7 +321,7 @@ Pydanticのようなデータのバリデーション、シリアライゼーシ /// -### Hug { #hug } +### [Hug](https://github.com/hugapi/hug) { #hug } Hugは、Pythonの型ヒントを利用してAPIパラメータの型宣言を実装した最初のフレームワークの1つです。これは素晴らしいアイデアで、他のツールが同じことをするきっかけとなりました。 @@ -337,7 +337,7 @@ OpenAPIやJSON Schemaのような標準に基づいたものではありませ /// info | 情報 -HugはTimothy Crosleyにより作成されました。彼は`isort`など、Pythonのファイル内のインポートの並び替えを自動的におこうなう素晴らしいツールの開発者です。 +HugはTimothy Crosleyにより作成されました。彼は[`isort`](https://github.com/timothycrosley/isort)など、Pythonのファイル内のインポートの並び替えを自動的におこうなう素晴らしいツールの開発者です。 /// @@ -351,7 +351,7 @@ Hugは、**FastAPI**がヘッダーやクッキーを設定するために関数 /// -### APIStar (<= 0.5) { #apistar-0-5 } +### [APIStar](https://github.com/encode/apistar) (<= 0.5) { #apistar-0-5 } **FastAPI**を構築することを決める直前に、**APIStar**サーバーを見つけました。それは私が探していたものがほぼすべて含まれており、素晴らしいデザインでした。 @@ -401,7 +401,7 @@ APIStarはTom Christieにより開発されました。以下の開発者でも ## **FastAPI**が利用しているもの { #used-by-fastapi } -### Pydantic { #pydantic } +### [Pydantic](https://docs.pydantic.dev/) { #pydantic } Pydanticは、Pythonの型ヒントを元にデータのバリデーション、シリアライゼーション、 (JSON Schemaを使用した) ドキュメントを定義するライブラリです。 @@ -413,11 +413,11 @@ Marshmallowに匹敵しますが、ベンチマークではMarshmallowよりも データのバリデーション、データのシリアライゼーション、自動的なモデルの (JSON Schemaに基づいた) ドキュメント化の全てを扱えます。 -**FastAPI**はJSON SchemaのデータをOpenAPIに利用します。 +**FastAPI**はそのJSON SchemaデータをOpenAPIに取り込みます (それ以外にも多くのことを行います)。 /// -### Starlette { #starlette } +### [Starlette](https://www.starlette.dev/) { #starlette } Starletteは、軽量なASGIフレームワーク/ツールキットで、高性能な非同期サービスの構築に最適です。 @@ -462,7 +462,7 @@ webに関するコアな部分を全て扱います。その上に機能を追 /// -### Uvicorn { #uvicorn } +### [Uvicorn](https://www.uvicorn.dev/) { #uvicorn } Uvicornは非常に高速なASGIサーバーで、uvloopとhttptoolsにより構成されています。 @@ -476,10 +476,10 @@ Starletteや**FastAPI**のサーバーとして推奨されています。 コマンドラインオプション `--workers` を使って、非同期のマルチプロセスサーバーにできます。 -詳細は[デプロイ](deployment/index.md){.internal-link target=_blank}の項目で確認してください。 +詳細は[デプロイ](deployment/index.md)の項目で確認してください。 /// ## ベンチマーク と スピード { #benchmarks-and-speed } -Uvicorn、Starlette、FastAPIの違いを理解、比較、確認するには、[ベンチマーク](benchmarks.md){.internal-link target=_blank}を確認してください。 +Uvicorn、Starlette、FastAPIの違いを理解、比較、確認するには、[ベンチマーク](benchmarks.md)を確認してください。 diff --git a/docs/ja/docs/async.md b/docs/ja/docs/async.md index bf4acda3f7..e2886d74e2 100644 --- a/docs/ja/docs/async.md +++ b/docs/ja/docs/async.md @@ -141,7 +141,7 @@ def results(): /// info | 情報 -美しいイラストは Ketrina Thompson によるものです。🎨 +美しいイラストは [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot) によるものです。🎨 /// @@ -207,7 +207,7 @@ def results(): /// info | 情報 -美しいイラストは Ketrina Thompson によるものです。🎨 +美しいイラストは [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot) によるものです。🎨 /// @@ -251,7 +251,7 @@ def results(): そして、それが **FastAPI** で得られるパフォーマンスの水準です。 -さらに、並列性と非同期性を同時に活用できるため、テストされた多くの NodeJS フレームワークより高い性能を発揮し、C に近いコンパイル言語である Go と同等の性能になります (すべて Starlette のおかげです)。 +さらに、並列性と非同期性を同時に活用できるため、テストされた多くの NodeJS フレームワークより高い性能を発揮し、C に近いコンパイル言語である Go と同等の性能になります [(すべて Starlette のおかげです)](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1)。 ### 並行処理は並列処理より優れている? { #is-concurrency-better-than-parallelism } @@ -298,7 +298,7 @@ CPU バウンドな操作の一般的な例は、複雑な数値処理が必要 さらに、Python が **データサイエンス**、機械学習、特にディープラーニングの主要言語であるという事実も相まって、FastAPI はデータサイエンス/機械学習の Web API やアプリケーション (ほか多数) に非常に適しています。 -本番環境でこの並列性を実現する方法は、[デプロイ](deployment/index.md){.internal-link target=_blank} のセクションを参照してください。 +本番環境でこの並列性を実現する方法は、[デプロイ](deployment/index.md) のセクションを参照してください。 ## `async` と `await` { #async-and-await } @@ -363,13 +363,13 @@ async def read_burgers(): ### 自分で async コードを書く { #write-your-own-async-code } -Starlette (**FastAPI** も) は AnyIO の上に構築されており、標準ライブラリの asyncioTrio の両方に対応しています。 +Starlette (**FastAPI** も) は [AnyIO](https://anyio.readthedocs.io/en/stable/) の上に構築されており、標準ライブラリの [asyncio](https://docs.python.org/3/library/asyncio-task.html) と [Trio](https://trio.readthedocs.io/en/stable/) の両方に対応しています。 -特に、あなた自身のコード内で、より高度なパターンを必要とする発展的な並行処理のユースケースに対して、AnyIO を直接使えます。 +特に、あなた自身のコード内で、より高度なパターンを必要とする発展的な並行処理のユースケースに対して、[AnyIO](https://anyio.readthedocs.io/en/stable/) を直接使えます。 -仮に FastAPI を使っていなくても、AnyIO で独自の async アプリケーションを書けば、高い互換性と利点 (例: 構造化並行性) を得られます。 +仮に FastAPI を使っていなくても、[AnyIO](https://anyio.readthedocs.io/en/stable/) で独自の async アプリケーションを書けば、高い互換性と利点 (例: 構造化並行性) を得られます。 -私は AnyIO の上に薄い層として、型注釈を少し改善し、より良い**補完**や**インラインエラー**などを得るための別ライブラリも作りました。また、**理解**して**自分で async コードを書く**のに役立つフレンドリーなイントロ/チュートリアルもあります: Asyncer。特に、**async コードと通常の** (ブロッキング/同期) **コードを組み合わせる**必要がある場合に有用です。 +私は AnyIO の上に薄い層として、型注釈を少し改善し、より良い**補完**や**インラインエラー**などを得るための別ライブラリも作りました。また、**理解**して**自分で async コードを書く**のに役立つフレンドリーなイントロ/チュートリアルもあります: [Asyncer](https://asyncer.tiangolo.com/)。特に、**async コードと通常の** (ブロッキング/同期) **コードを組み合わせる**必要がある場合に有用です。 ### 非同期コードの他の形式 { #other-forms-of-asynchronous-code } @@ -381,7 +381,7 @@ Starlette (**FastAPI** も) は Gevent を使えましたが、コードの理解・デバッグ・思考がはるかに難しくなります。 +以前の Python ではスレッドや [Gevent](https://www.gevent.org/) を使えましたが、コードの理解・デバッグ・思考がはるかに難しくなります。 以前の NodeJS / ブラウザ JavaScript では「コールバック」を使っており、「コールバック地獄」を招きました。 @@ -419,15 +419,15 @@ Starlette (**FastAPI** も) は I/O を行うコードを使っていない限り、`async def` を使った方が良いです。 -それでも、どちらの状況でも、**FastAPI** はあなたが以前使っていたフレームワークよりも (少なくとも同等に) [高速である](index.md#performance){.internal-link target=_blank} 可能性が高いです。 +それでも、どちらの状況でも、**FastAPI** はあなたが以前使っていたフレームワークよりも (少なくとも同等に) [高速である](index.md#performance) 可能性が高いです。 ### 依存関係 { #dependencies } -[依存関係](tutorial/dependencies/index.md){.internal-link target=_blank} についても同様です。依存関係が `async def` ではなく標準の `def` 関数である場合、外部のスレッドプールで実行されます。 +[依存関係](tutorial/dependencies/index.md) についても同様です。依存関係が `async def` ではなく標準の `def` 関数である場合、外部のスレッドプールで実行されます。 ### サブ依存関係 { #sub-dependencies } -複数の依存関係や [サブ依存関係](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} を (関数定義のパラメータとして) 相互に要求させられます。その一部は `async def`、他は通常の `def` で作られていても動作します。通常の `def` で作られたものは「await」される代わりに、外部スレッドプールからスレッド上で呼び出されます。 +複数の依存関係や [サブ依存関係](tutorial/dependencies/sub-dependencies.md) を (関数定義のパラメータとして) 相互に要求させられます。その一部は `async def`、他は通常の `def` で作られていても動作します。通常の `def` で作られたものは「await」される代わりに、外部スレッドプールからスレッド上で呼び出されます。 ### その他のユーティリティ関数 { #other-utility-functions } diff --git a/docs/ja/docs/benchmarks.md b/docs/ja/docs/benchmarks.md index fbfba2e637..b6ed4d6d29 100644 --- a/docs/ja/docs/benchmarks.md +++ b/docs/ja/docs/benchmarks.md @@ -1,6 +1,6 @@ # ベンチマーク { #benchmarks } -TechEmpowerの独立したベンチマークでは、Uvicornの下で動作する**FastAPI**アプリケーションは、利用可能な最速のPythonフレームワークの1つであり、下回っているのはStarletteとUvicorn自体(FastAPIによって内部で使用される)のみだと示されています。 +TechEmpowerの独立したベンチマークでは、Uvicornの下で動作する**FastAPI**アプリケーションは、[利用可能な最速のPythonフレームワークの1つ](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7)であり、下回っているのはStarletteとUvicorn自体(FastAPIによって内部で使用される)のみだと示されています。 ただし、ベンチマークを確認し、比較する際には下記の内容に気を付けてください。 diff --git a/docs/ja/docs/deployment/cloud.md b/docs/ja/docs/deployment/cloud.md index 17699cdca6..8357464fbf 100644 --- a/docs/ja/docs/deployment/cloud.md +++ b/docs/ja/docs/deployment/cloud.md @@ -6,7 +6,7 @@ FastAPI アプリケーションは、実質的にどのようなクラウドプ ## FastAPI Cloud { #fastapi-cloud } -**FastAPI Cloud** は、**FastAPI** の作者と同じチームによって作られています。 +**[FastAPI Cloud](https://fastapicloud.com)** は、**FastAPI** の作者と同じチームによって作られています。 API の**構築**、**デプロイ**、**アクセス**までのプロセスを、最小限の手間で効率化します。 @@ -16,9 +16,9 @@ FastAPI Cloud は、*FastAPI and friends* オープンソースプロジェク ## クラウドプロバイダ - スポンサー { #cloud-providers-sponsors } -他にもいくつかのクラウドプロバイダが ✨ [**FastAPI をスポンサーしています**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨。🙇 +他にもいくつかのクラウドプロバイダが ✨ [**FastAPI をスポンサーしています**](../help-fastapi.md#sponsor-the-author) ✨。🙇 それらのガイドを参考にし、サービスを試してみるのもよいでしょう: -* Render -* Railway +* [Render](https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi) +* [Railway](https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi) diff --git a/docs/ja/docs/deployment/concepts.md b/docs/ja/docs/deployment/concepts.md index 501a90bc93..9a23e8e914 100644 --- a/docs/ja/docs/deployment/concepts.md +++ b/docs/ja/docs/deployment/concepts.md @@ -29,7 +29,7 @@ ## セキュリティ - HTTPS { #security-https } -[前チャプターのHTTPSについて](https.md){.internal-link target=_blank}では、HTTPSがどのようにAPIを暗号化するのかについて学びました。 +[前チャプターのHTTPSについて](https.md)では、HTTPSがどのようにAPIを暗号化するのかについて学びました。 通常、アプリケーションサーバにとって**外部の**コンポーネントである**TLS Termination Proxy**によって提供されることが一般的です。このプロキシは通信の暗号化を担当します。 @@ -43,9 +43,9 @@ TLS Termination Proxyとして使用できるツールには以下のような * Caddy * 証明書の更新を自動的に処理 ✨ * Nginx - * 証明書更新のためにCertbotのような外部コンポーネントを使用 + * 証明書更新のために Certbot のような外部コンポーネントを使用 * HAProxy - * 証明書更新のためにCertbotのような外部コンポーネントを使用 + * 証明書更新のために Certbot のような外部コンポーネントを使用 * Nginx のような Ingress Controller を持つ Kubernetes * 証明書の更新に cert-manager のような外部コンポーネントを使用 * クラウド・プロバイダーがサービスの一部として内部的に処理(下記を参照👇) @@ -193,7 +193,7 @@ FastAPI アプリケーションでは、Uvicorn を実行する `fastapi` コ ### ワーカー・プロセス と ポート { #worker-processes-and-ports } -[HTTPSについて](https.md){.internal-link target=_blank}のドキュメントで、1つのサーバーで1つのポートとIPアドレスの組み合わせでリッスンできるのは1つのプロセスだけであることを覚えていますでしょうか? +[HTTPSについて](https.md)のドキュメントで、1つのサーバーで1つのポートとIPアドレスの組み合わせでリッスンできるのは1つのプロセスだけであることを覚えていますでしょうか? これはいまだに同じです。 @@ -250,7 +250,7 @@ FastAPI アプリケーションでは、Uvicorn を実行する `fastapi` コ これらの**コンテナ**やDockerそしてKubernetesに関する項目が、まだあまり意味をなしていなくても心配しないでください。 -コンテナ・イメージ、Docker、Kubernetesなどについては、将来の章で詳しく説明します: [コンテナ内のFastAPI - Docker](docker.md){.internal-link target=_blank}. +コンテナ・イメージ、Docker、Kubernetesなどについては、将来の章で詳しく説明します: [コンテナ内のFastAPI - Docker](docker.md). /// @@ -290,7 +290,7 @@ FastAPI アプリケーションでは、Uvicorn を実行する `fastapi` コ /// tip | 豆知識 -コンテナを使った具体的な例については、将来の章で紹介します: [コンテナ内のFastAPI - Docker](docker.md){.internal-link target=_blank}. +コンテナを使った具体的な例については、将来の章で紹介します: [コンテナ内のFastAPI - Docker](docker.md). /// diff --git a/docs/ja/docs/deployment/docker.md b/docs/ja/docs/deployment/docker.md index 883f98c985..6248e69b7c 100644 --- a/docs/ja/docs/deployment/docker.md +++ b/docs/ja/docs/deployment/docker.md @@ -1,6 +1,6 @@ # コンテナ内のFastAPI - Docker { #fastapi-in-containers-docker } -FastAPIアプリケーションをデプロイする場合、一般的なアプローチは**Linuxコンテナ・イメージ**をビルドすることです。基本的には **Docker**を用いて行われます。生成されたコンテナ・イメージは、いくつかの方法のいずれかでデプロイできます。 +FastAPIアプリケーションをデプロイする場合、一般的なアプローチは**Linuxコンテナ・イメージ**をビルドすることです。基本的には [**Docker**](https://www.docker.com/) を用いて行われます。生成されたコンテナ・イメージは、いくつかの方法のいずれかでデプロイできます。 Linuxコンテナの使用には、**セキュリティ**、**反復可能性(レプリカビリティ)**、**シンプリシティ**など、いくつかの利点があります。 @@ -60,16 +60,16 @@ Linuxコンテナは、ホスト(マシン、仮想マシン、クラウドサ Dockerは、**コンテナ・イメージ**と**コンテナ**を作成・管理するための主要なツールの1つです。 -そして、多くのツールや環境、データベース、アプリケーションに対応している予め作成された**公式のコンテナ・イメージ**をパブリックに提供しているDocker Hubというものがあります。 +そして、多くのツールや環境、データベース、アプリケーションに対応している予め作成された**公式のコンテナ・イメージ**をパブリックに提供している [Docker Hub](https://hub.docker.com/) というものがあります。 -例えば、公式イメージの1つにPython Imageがあります。 +例えば、公式イメージの1つに [Python Image](https://hub.docker.com/_/python) があります。 その他にも、データベースなどさまざまなイメージがあります: -* PostgreSQL -* MySQL -* MongoDB -* Redis, etc. +* [PostgreSQL](https://hub.docker.com/_/postgres) +* [MySQL](https://hub.docker.com/_/mysql) +* [MongoDB](https://hub.docker.com/_/mongo) +* [Redis](https://hub.docker.com/_/redis), etc. 予め作成されたコンテナ・イメージを使用することで、異なるツールを**組み合わせて**使用することが非常に簡単になります。例えば、新しいデータベースを試す場合に特に便利です。ほとんどの場合、**公式イメージ**を使い、環境変数で設定するだけで良いです。 @@ -111,7 +111,7 @@ FastAPI用の**Dockerイメージ**を、**公式Python**イメージに基づ 最も一般的な方法は、`requirements.txt` ファイルにパッケージ名とそのバージョンを 1 行ずつ書くことです。 -もちろん、[FastAPI バージョンについて](versions.md){.internal-link target=_blank}で読んだのと同じアイデアを使用して、バージョンの範囲を設定します。 +もちろん、[FastAPI バージョンについて](versions.md)で読んだのと同じアイデアを使用して、バージョンの範囲を設定します。 例えば、`requirements.txt` は次のようになります: @@ -238,7 +238,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] #### `CMD` を使う - Exec形式 { #use-cmd-exec-form } -Docker命令 `CMD` は2つの形式で書けます: +Docker命令 [`CMD`](https://docs.docker.com/reference/dockerfile/#cmd) は2つの形式で書けます: ✅ **Exec** 形式: @@ -254,11 +254,11 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] CMD fastapi run app/main.py --port 80 ``` -FastAPIが正常にシャットダウンでき、[lifespan events](../advanced/events.md){.internal-link target=_blank}がトリガーされるように、常に **exec** 形式を使用してください。 +FastAPIが正常にシャットダウンでき、[lifespan events](../advanced/events.md)がトリガーされるように、常に **exec** 形式を使用してください。 -詳しくは、shell形式とexec形式に関するDockerドキュメントをご覧ください。 +詳しくは、[shell形式とexec形式に関するDockerドキュメント](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form)をご覧ください。 -これは `docker compose` を使用する場合にかなり目立つことがあります。より技術的な詳細は、このDocker ComposeのFAQセクションをご覧ください:Why do my services take 10 seconds to recreate or stop?。 +これは `docker compose` を使用する場合にかなり目立つことがあります。より技術的な詳細は、このDocker ComposeのFAQセクションをご覧ください:[Why do my services take 10 seconds to recreate or stop?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop)。 #### ディレクトリ構造 { #directory-structure } @@ -354,7 +354,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage ## 確認する { #check-it } -Dockerコンテナのhttp://192.168.99.100/items/5?q=somequeryhttp://127.0.0.1/items/5?q=somequery (またはそれに相当するDockerホストを使用したもの)といったURLで確認できるはずです。 +Dockerコンテナの[http://192.168.99.100/items/5?q=somequery](http://192.168.99.100/items/5?q=somequery) や [http://127.0.0.1/items/5?q=somequery](http://127.0.0.1/items/5?q=somequery) (またはそれに相当するDockerホストを使用したもの)といったURLで確認できるはずです。 アクセスすると以下のようなものが表示されます: @@ -364,17 +364,17 @@ Dockerコンテナのhttp://192.168.99.100/docshttp://127.0.0.1/docs (またはそれに相当するDockerホストを使用したもの) +これらのURLにもアクセスできます: [http://192.168.99.100/docs](http://192.168.99.100/docs) や [http://127.0.0.1/docs](http://127.0.0.1/docs) (またはそれに相当するDockerホストを使用したもの) -アクセスすると、自動対話型APIドキュメント(Swagger UIが提供)が表示されます: +アクセスすると、自動対話型APIドキュメント([Swagger UI](https://github.com/swagger-api/swagger-ui)が提供)が表示されます: ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) ## 代替のAPIドキュメント { #alternative-api-docs } -また、http://192.168.99.100/redochttp://127.0.0.1/redoc (またはそれに相当するDockerホストを使用したもの)にもアクセスできます。 +また、[http://192.168.99.100/redoc](http://192.168.99.100/redoc) や [http://127.0.0.1/redoc](http://127.0.0.1/redoc) (またはそれに相当するDockerホストを使用したもの)にもアクセスできます。 -代替の自動ドキュメント(ReDocによって提供される)が表示されます: +代替の自動ドキュメント([ReDoc](https://github.com/Rebilly/ReDoc)によって提供される)が表示されます: ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -415,7 +415,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] ## デプロイメントのコンセプト { #deployment-concepts } -コンテナという観点から、[デプロイのコンセプト](concepts.md){.internal-link target=_blank}に共通するいくつかについて、もう一度説明しましょう。 +コンテナという観点から、[デプロイのコンセプト](concepts.md)に共通するいくつかについて、もう一度説明しましょう。 コンテナは主に、アプリケーションの**ビルドとデプロイ**のプロセスを簡素化するためのツールですが、これらの**デプロイのコンセプト**を扱うための特定のアプローチを強制するものではなく、いくつかの戦略があります。 @@ -434,7 +434,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] FastAPI アプリケーションの **コンテナ・イメージ**(および後で実行中の **コンテナ**)だけに焦点を当てると、通常、HTTPSは別のツールを用いて**外部で**処理されます。 -例えばTraefikのように、**HTTPS**と**証明書**の**自動**取得を扱う別のコンテナである可能性もあります。 +例えば [Traefik](https://traefik.io/) のように、**HTTPS**と**証明書**の**自動**取得を扱う別のコンテナである可能性もあります。 /// tip | 豆知識 @@ -564,7 +564,7 @@ Docker Composeで**単一サーバ**(クラスタではない)にデプロ /// info | 情報 -もしKubernetesを使用している場合, これはおそらくInit Containerでしょう。 +もしKubernetesを使用している場合, これはおそらく[Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)でしょう。 /// @@ -576,7 +576,7 @@ Docker Composeで**単一サーバ**(クラスタではない)にデプロ ### ベースDockerイメージ { #base-docker-image } -以前は、公式のFastAPI Dockerイメージがありました:tiangolo/uvicorn-gunicorn-fastapi。しかし、現在は非推奨です。⛔️ +以前は、公式のFastAPI Dockerイメージがありました:[tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker)。しかし、現在は非推奨です。⛔️ おそらく、このベースDockerイメージ(またはその他の類似のもの)は**使用しない**方がよいでしょう。 @@ -606,7 +606,7 @@ Docker Composeで**単一サーバ**(クラスタではない)にデプロ ## `uv` を使ったDockerイメージ { #docker-image-with-uv } -uv を使ってプロジェクトのインストールと管理をしている場合は、uv Docker guideに従ってください。 +[uv](https://github.com/astral-sh/uv) を使ってプロジェクトのインストールと管理をしている場合は、[uv Docker guide](https://docs.astral.sh/uv/guides/integration/docker/)に従ってください。 ## まとめ { #recap } diff --git a/docs/ja/docs/deployment/fastapicloud.md b/docs/ja/docs/deployment/fastapicloud.md index 43d9ce0d02..3dd5685a2b 100644 --- a/docs/ja/docs/deployment/fastapicloud.md +++ b/docs/ja/docs/deployment/fastapicloud.md @@ -1,6 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -FastAPI Cloud に **コマンド1つ** でデプロイできます。まだならウェイティングリストにご登録ください。🚀 +[FastAPI Cloud](https://fastapicloud.com) に **コマンド1つ** でデプロイできます。まだならウェイティングリストにご登録ください。🚀 ## ログイン { #login } @@ -40,7 +40,7 @@ Deploying to FastAPI Cloud... ## FastAPI Cloud について { #about-fastapi-cloud } -**FastAPI Cloud** は、**FastAPI** の作者とチームによって開発されています。 +**[FastAPI Cloud](https://fastapicloud.com)** は、**FastAPI** の作者とチームによって開発されています。 最小限の手間で API を**構築**・**デプロイ**・**利用**できるように工程を簡素化します。 diff --git a/docs/ja/docs/deployment/https.md b/docs/ja/docs/deployment/https.md index 8e588aadc3..37ad7072c8 100644 --- a/docs/ja/docs/deployment/https.md +++ b/docs/ja/docs/deployment/https.md @@ -10,7 +10,7 @@ HTTPSは単に「有効」か「無効」かで決まるものだと思いがち /// -利用者の視点から **HTTPS の基本を学ぶ**に当たっては、次のリソースをオススメします: https://howhttps.works/. +利用者の視点から **HTTPS の基本を学ぶ**に当たっては、次のリソースをオススメします: [https://howhttps.works/](https://howhttps.works/). さて、**開発者の視点**から、HTTPSについて考える際に念頭に置くべきことをいくつかみていきましょう: @@ -28,13 +28,13 @@ HTTPSは単に「有効」か「無効」かで決まるものだと思いがち * **デフォルトでは**、**IPアドレスごとに1つのHTTPS証明書**しか持てないことになります。 * これは、サーバーの規模やアプリケーションの規模に寄りません。 * しかし、これには**解決策**があります。 -* **TLS**プロトコル(HTTPの前に、TCPレベルで暗号化を処理するもの)には、**SNI**と呼ばれる**拡張**があります。 +* **TLS**プロトコル(HTTPの前に、TCPレベルで暗号化を処理するもの)には、**[SNI](https://en.wikipedia.org/wiki/Server_Name_Indication)**と呼ばれる**拡張**があります。 * このSNI拡張機能により、1つのサーバー(**単一のIPアドレス**を持つ)が**複数のHTTPS証明書**を持ち、**複数のHTTPSドメイン/アプリケーション**にサービスを提供できるようになります。 * これが機能するためには、**パブリックIPアドレス**でリッスンしている、サーバー上で動作している**単一の**コンポーネント(プログラム)が、サーバー内の**すべてのHTTPS証明書**を持っている必要があります。 * セキュアな接続を取得した**後**でも、通信プロトコルは**HTTPのまま**です。 * コンテンツは**HTTPプロトコル**で送信されているにもかかわらず、**暗号化**されています。 -サーバー(マシン、ホストなど)上で**1つのプログラム/HTTPサーバー**を実行させ、**HTTPSに関する全てのこと**を管理するのが一般的です。**暗号化された HTTPS リクエスト** を受信し、**復号化された HTTP リクエスト** を同じサーバーで実行されている実際の HTTP アプリケーション(この場合は **FastAPI** アプリケーション)に送信し、アプリケーションから **HTTP レスポンス** を受け取り、適切な **HTTPS 証明書** を使用して **暗号化** し、そして**HTTPS** を使用してクライアントに送り返します。このサーバーはしばしば **TLS Termination Proxy**と呼ばれます。 +サーバー(マシン、ホストなど)上で**1つのプログラム/HTTPサーバー**を実行させ、**HTTPSに関する全てのこと**を管理するのが一般的です。**暗号化された HTTPS リクエスト** を受信し、**復号化された HTTP リクエスト** を同じサーバーで実行されている実際の HTTP アプリケーション(この場合は **FastAPI** アプリケーション)に送信し、アプリケーションから **HTTP レスポンス** を受け取り、適切な **HTTPS 証明書** を使用して **暗号化** し、そして**HTTPS** を使用してクライアントに送り返します。このサーバーはしばしば **[TLS Termination Proxy](https://en.wikipedia.org/wiki/TLS_termination_proxy)**と呼ばれます。 TLS Termination Proxyとして使えるオプションには、以下のようなものがあります: @@ -50,7 +50,7 @@ Let's Encrypt以前は、これらの**HTTPS証明書**は信頼できる第三 これらの証明書を取得するための手続きは面倒で、かなりの書類を必要とし、証明書はかなり高価なものでした。 -しかしその後、**Let's Encrypt** が作られました。 +しかしその後、**[Let's Encrypt](https://letsencrypt.org/)** が作られました。 これはLinux Foundationのプロジェクトから生まれたものです。 自動化された方法で、**HTTPS証明書を無料で**提供します。これらの証明書は、すべての標準的な暗号化セキュリティを使用し、また短命(約3ヶ月)ですが、こういった寿命の短さによって、**セキュリティは実際に優れています**。 @@ -68,7 +68,7 @@ Let's Encrypt以前は、これらの**HTTPS証明書**は信頼できる第三 おそらくクラウドサーバー(仮想マシン)かそれに類するものを手に入れ、固定の **パブリックIPアドレス**を持つことになるでしょう。 -DNSサーバーでは、**取得したドメイン**をあなたのサーバーのパプリック**IPアドレス**に向けるレコード(「`A record`」)を設定します。 +DNSサーバーでは、**取得したドメイン**をあなたのサーバーのパブリック**IPアドレス**に向けるレコード(「`A record`」)を設定します。 これはおそらく、最初の1回だけあり、すべてをセットアップするときに行うでしょう。 @@ -80,7 +80,7 @@ DNSサーバーでは、**取得したドメイン**をあなたのサーバー ### DNS { #dns } -では、実際のHTTPSの部分に注目してみよう。 +では、実際のHTTPSの部分に注目してみましょう。 まず、ブラウザは**DNSサーバー**に**ドメインに対するIP**が何であるかを確認します。今回は、`someapp.example.com`とします。 @@ -100,7 +100,7 @@ TLS接続を確立するためのクライアントとサーバー間のこの ### SNI拡張機能付きのTLS { #tls-with-sni-extension } -サーバー内の**1つのプロセス**だけが、特定 の**IPアドレス**の特定の**ポート** で待ち受けることができます。 +サーバー内の**1つのプロセス**だけが、特定の**IPアドレス**の特定の**ポート**で待ち受けることができます。 同じIPアドレスの他のポートで他のプロセスがリッスンしている可能性もありますが、IPアドレスとポートの組み合わせごとに1つだけです。 @@ -204,9 +204,9 @@ TLS Termination Proxyは次に、事前に合意が取れている暗号(`someap プロキシヘッダーは次のとおりです: -* X-Forwarded-For -* X-Forwarded-Proto -* X-Forwarded-Host +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) /// @@ -222,7 +222,7 @@ TLS Termination Proxyは次に、事前に合意が取れている暗号(`someap /// tip | 豆知識 -これについては、[Behind a Proxy - Enable Proxy Forwarded Headers](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} のドキュメントで詳しく学べます。 +これについては、[Behind a Proxy - Enable Proxy Forwarded Headers](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) のドキュメントで詳しく学べます。 /// diff --git a/docs/ja/docs/deployment/index.md b/docs/ja/docs/deployment/index.md index eba6eae6ea..9a3e1068e6 100644 --- a/docs/ja/docs/deployment/index.md +++ b/docs/ja/docs/deployment/index.md @@ -16,7 +16,7 @@ 複数のツールを組み合わせて自分で**サーバーをデプロイ**することもできますし、作業の一部を代行してくれる **クラウドサービス** を使うこともできます。ほかにも選択肢があります。 -たとえば、FastAPI の開発チームである私たちは、クラウドへの FastAPI アプリのデプロイを可能な限り合理化し、FastAPI を使って開発するのと同じ開発者体験を提供するために、**FastAPI Cloud** を構築しました。 +たとえば、FastAPI の開発チームである私たちは、クラウドへの FastAPI アプリのデプロイを可能な限り合理化し、FastAPI を使って開発するのと同じ開発者体験を提供するために、[**FastAPI Cloud**](https://fastapicloud.com) を構築しました。 **FastAPI** アプリケーションをデプロイする際に、おそらく念頭に置くべき主要な概念をいくつか紹介します(ただし、そのほとんどは他の種類の Web アプリケーションにも当てはまります)。 diff --git a/docs/ja/docs/deployment/manually.md b/docs/ja/docs/deployment/manually.md index 1931cd87e5..1c0d59a715 100644 --- a/docs/ja/docs/deployment/manually.md +++ b/docs/ja/docs/deployment/manually.md @@ -52,11 +52,11 @@ FastAPI は、Python の Web フレームワークとサーバーのための標 他にもいくつかの選択肢があります: -* Uvicorn: 高性能な ASGI サーバー。 -* Hypercorn: HTTP/2 や Trio に対応する ASGI サーバーなど。 -* Daphne: Django Channels のために作られた ASGI サーバー。 -* Granian: Python アプリケーション向けの Rust 製 HTTP サーバー。 -* NGINX Unit: 軽量で多用途な Web アプリケーションランタイム。 +* [Uvicorn](https://www.uvicorn.dev/): 高性能な ASGI サーバー。 +* [Hypercorn](https://hypercorn.readthedocs.io/): HTTP/2 や Trio に対応する ASGI サーバーなど。 +* [Daphne](https://github.com/django/daphne): Django Channels のために作られた ASGI サーバー。 +* [Granian](https://github.com/emmett-framework/granian): Python アプリケーション向けの Rust 製 HTTP サーバー。 +* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): 軽量で多用途な Web アプリケーションランタイム。 ## サーバーマシンとサーバープログラム { #server-machine-and-server-program } @@ -74,7 +74,7 @@ FastAPI をインストールすると、本番サーバーの Uvicorn が同梱 ただし、ASGI サーバーを手動でインストールすることもできます。 -[仮想環境](../virtual-environments.md){.internal-link target=_blank}を作成して有効化し、サーバーアプリケーションをインストールしてください。 +[仮想環境](../virtual-environments.md)を作成して有効化し、サーバーアプリケーションをインストールしてください。 例として、Uvicorn をインストールするには: @@ -94,7 +94,7 @@ $ pip install "uvicorn[standard]" `standard` を付けると、Uvicorn は推奨の追加依存関係もインストールして使用します。 -その中には、`asyncio` の高性能なドロップイン代替であり、大きな並行実行性能の向上をもたらす `uvloop` も含まれます。 +その中には、`uvloop` も含まれます。これは `asyncio` の高性能なドロップイン代替で、大きな並行実行性能の向上をもたらします。 `pip install "fastapi[standard]"` のように FastAPI をインストールした場合は、すでに `uvicorn[standard]` も含まれます。 diff --git a/docs/ja/docs/deployment/server-workers.md b/docs/ja/docs/deployment/server-workers.md index 933b875d76..c4c6e93557 100644 --- a/docs/ja/docs/deployment/server-workers.md +++ b/docs/ja/docs/deployment/server-workers.md @@ -13,13 +13,13 @@ アプリケーションをデプロイする際には、**複数のコア**を利用し、そしてより多くのリクエストを処理できるようにするために、プロセスの**レプリケーション**を持つことを望むでしょう。 -前のチャプターである[デプロイメントのコンセプト](concepts.md){.internal-link target=_blank}にて見てきたように、有効な戦略がいくつかあります。 +前のチャプターである[デプロイメントのコンセプト](concepts.md)にて見てきたように、有効な戦略がいくつかあります。 ここでは、`fastapi` コマンド、または `uvicorn` コマンドを直接使って、**ワーカープロセス**付きの **Uvicorn** を使う方法を紹介します。 /// info | 情報 -DockerやKubernetesなどのコンテナを使用している場合は、次の章で詳しく説明します: [コンテナ内のFastAPI - Docker](docker.md){.internal-link target=_blank}。 +DockerやKubernetesなどのコンテナを使用している場合は、次の章で詳しく説明します: [コンテナ内のFastAPI - Docker](docker.md)。 特に**Kubernetes**上で実行する場合は、おそらくワーカーは使わず、代わりに**コンテナごとに単一のUvicornプロセス**を実行したいはずですが、それについてはその章の後半で説明します。 @@ -126,7 +126,7 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 ## コンテナとDocker { #containers-and-docker } -次章の[コンテナ内のFastAPI - Docker](docker.md){.internal-link target=_blank}では、その他の**デプロイメントのコンセプト**を扱うために使える戦略をいくつか説明します。 +次章の[コンテナ内のFastAPI - Docker](docker.md)では、その他の**デプロイメントのコンセプト**を扱うために使える戦略をいくつか説明します。 単一のUvicornプロセスを実行するために、**ゼロから独自のイメージを構築する**方法も紹介します。これは簡単なプロセスで、**Kubernetes**のような分散コンテナ管理システムを使う場合に、おそらくやりたいことでしょう。 diff --git a/docs/ja/docs/deployment/versions.md b/docs/ja/docs/deployment/versions.md index 7980b8be2a..36e22636c8 100644 --- a/docs/ja/docs/deployment/versions.md +++ b/docs/ja/docs/deployment/versions.md @@ -4,7 +4,7 @@ 新機能が高頻度で追加され、定期的にバグが修正され、コードは継続的に改善されています。 -これが現在のバージョンがいまだに `0.x.x` な理由であり、それぞれのバージョンは破壊的な変更がなされる可能性があります。これは、セマンティック バージョニングの規則に則っています。 +これが現在のバージョンがいまだに `0.x.x` な理由であり、それぞれのバージョンは破壊的な変更がなされる可能性があります。これは、[セマンティック バージョニング](https://semver.org/)の規則に則っています。 **FastAPI** を使用すると本番用アプリケーションを今すぐ作成できます(そして、おそらくあなたはしばらく前からそうしているはずです)。必要なのは、残りのコードと正しく動作するバージョンを使用していることを確認することだけです。 @@ -34,7 +34,7 @@ fastapi[standard]>=0.112.0,<0.113.0 ## 利用可能なバージョン { #available-versions } -利用可能なバージョン(例: 現在の最新が何かを確認するため)は、[Release Notes](../release-notes.md){.internal-link target=_blank} で確認できます。 +利用可能なバージョン(例: 現在の最新が何かを確認するため)は、[Release Notes](../release-notes.md) で確認できます。 ## バージョンについて { #about-versions } @@ -66,7 +66,7 @@ fastapi>=0.45.0,<0.46.0 アプリケーションにテストを追加すべきです。 -**FastAPI** では非常に簡単に実現できます(Starlette のおかげです)。ドキュメントを確認して下さい: [テスト](../tutorial/testing.md){.internal-link target=_blank} +**FastAPI** では非常に簡単に実現できます(Starlette のおかげです)。ドキュメントを確認して下さい: [テスト](../tutorial/testing.md) テストを追加したら、**FastAPI** のバージョンをより新しいものにアップグレードし、テストを実行することで全てのコードが正しく動作するか確認できます。 diff --git a/docs/ja/docs/environment-variables.md b/docs/ja/docs/environment-variables.md index 4deae70446..846f328461 100644 --- a/docs/ja/docs/environment-variables.md +++ b/docs/ja/docs/environment-variables.md @@ -2,7 +2,7 @@ /// tip | 豆知識 -もし、「環境変数」とは何か、それをどう使うかを既に知っている場合は、このセクションをスキップして構いません。 +もし「環境変数」とは何か、それをどう使うかを既に知っている場合は、このセクションをスキップして構いません。 /// @@ -19,10 +19,10 @@
```console -// You could create an env var MY_NAME with +// 環境変数 MY_NAME を作成する例 $ export MY_NAME="Wade Wilson" -// Then you could use it with other programs, like +// その後、他のプログラムで利用できます。例えば $ echo "Hello $MY_NAME" Hello Wade Wilson @@ -37,10 +37,10 @@ Hello Wade Wilson
```console -// Create an env var MY_NAME +// 環境変数 MY_NAME を作成 $ $Env:MY_NAME = "Wade Wilson" -// Use it with other programs, like +// 他のプログラムで利用、例えば $ echo "Hello $Env:MY_NAME" Hello Wade Wilson @@ -65,7 +65,7 @@ print(f"Hello {name} from Python") /// tip | 豆知識 -`os.getenv()` の第2引数は、デフォルトで返される値です。 +[`os.getenv()`](https://docs.python.org/3.8/library/os.html#os.getenv) の第2引数は、返されるデフォルト値です。 指定しない場合、デフォルトは`None`ですが、ここでは使用するデフォルト値として`"World"`を指定しています。 @@ -78,20 +78,20 @@ print(f"Hello {name} from Python")
```console -// Here we don't set the env var yet +// ここではまだ環境変数を設定していません $ python main.py -// As we didn't set the env var, we get the default value +// 環境変数を設定していないため、デフォルト値が使われます Hello World from Python -// But if we create an environment variable first +// しかし、先に環境変数を作成すると $ export MY_NAME="Wade Wilson" -// And then call the program again +// それからもう一度プログラムを実行すると $ python main.py -// Now it can read the environment variable +// すると環境変数を読み取れます Hello Wade Wilson from Python ``` @@ -105,20 +105,20 @@ Hello Wade Wilson from Python
```console -// Here we don't set the env var yet +// ここではまだ環境変数を設定していません $ python main.py -// As we didn't set the env var, we get the default value +// 環境変数を設定していないため、デフォルト値が使われます Hello World from Python -// But if we create an environment variable first +// しかし、先に環境変数を作成すると $ $Env:MY_NAME = "Wade Wilson" -// And then call the program again +// それからもう一度プログラムを実行すると $ python main.py -// Now it can read the environment variable +// すると環境変数を読み取れます Hello Wade Wilson from Python ``` @@ -136,14 +136,14 @@ Hello Wade Wilson from Python
```console -// Create an env var MY_NAME in line for this program call +// このプログラム呼び出し用に同じ行で環境変数 MY_NAME を作成 $ MY_NAME="Wade Wilson" python main.py -// Now it can read the environment variable +// これで環境変数を読み取れます Hello Wade Wilson from Python -// The env var no longer exists afterwards +// その後は環境変数は存在しません $ python main.py Hello World from Python @@ -153,7 +153,7 @@ Hello World from Python /// tip | 豆知識 -詳しくは The Twelve-Factor App: 設定 を参照してください。 +詳しくは [The Twelve-Factor App: 設定](https://12factor.net/config) を参照してください。 /// @@ -163,7 +163,7 @@ Hello World from Python つまり、環境変数からPythonで読み取る**あらゆる値**は **`str`になり**、他の型への変換やバリデーションはコード内で行う必要があります。 -環境変数を使って**アプリケーション設定**を扱う方法については、[高度なユーザーガイド - Settings and Environment Variables](./advanced/settings.md){.internal-link target=_blank} で詳しく学べます。 +環境変数を使って**アプリケーション設定**を扱う方法については、[高度なユーザーガイド - Settings and Environment Variables](./advanced/settings.md)で詳しく学べます。 ## `PATH`環境変数 { #path-environment-variable } @@ -285,13 +285,13 @@ $ C:\opt\custompython\bin\python //// -この情報は、[Virtual Environments](virtual-environments.md){.internal-link target=_blank} について学ぶ際にも役立ちます。 +この情報は、[Virtual Environments](virtual-environments.md)について学ぶ際にも役立ちます。 ## まとめ { #conclusion } これで、**環境変数**とは何か、Pythonでどのように使用するかについて、基本的な理解が得られたはずです。 -環境変数についての詳細は、Wikipedia の環境変数 も参照してください。 +環境変数についての詳細は、[Wikipedia の環境変数](https://en.wikipedia.org/wiki/Environment_variable)も参照してください。 多くの場合、環境変数がどのように役立ち、すぐに適用できるのかはあまり明確ではありません。しかし、開発中のさまざまなシナリオで何度も登場するため、知っておくとよいでしょう。 diff --git a/docs/ja/docs/fastapi-cli.md b/docs/ja/docs/fastapi-cli.md index 20cc9c2fb8..298ed91416 100644 --- a/docs/ja/docs/fastapi-cli.md +++ b/docs/ja/docs/fastapi-cli.md @@ -1,15 +1,15 @@ # FastAPI CLI { #fastapi-cli } -**FastAPI CLI** は、FastAPI アプリの提供、FastAPI プロジェクトの管理などに使用できるコマンドラインプログラムです。 +**FastAPI CLI** は、FastAPI アプリの提供、FastAPI プロジェクトの管理などに使用できるコマンドラインプログラムです。 -FastAPI をインストールすると(例: `pip install "fastapi[standard]"`)、`fastapi-cli` というパッケージが含まれます。このパッケージがターミナルで使用する `fastapi` コマンドを提供します。 +FastAPI をインストールすると(例: `pip install "fastapi[standard]"`)、ターミナルで実行できるコマンドラインプログラムが付属します。 開発用に FastAPI アプリを起動するには、`fastapi dev` コマンドを使用できます:
```console -$ fastapi dev main.py +$ fastapi dev FastAPI Starting development server 🚀 @@ -46,13 +46,66 @@ $ fastapi dev Uvicorn(高性能で本番運用向けの ASGI サーバー)を使用します。😎 +さらに、[VS Code 拡張機能](editor-support.md) や [FastAPI Cloud](https://fastapicloud.com) など、ほかのツールがそれを見つけられない場合があります。そのため、`pyproject.toml` の `entrypoint` を使用することを推奨します。 ## `fastapi dev` { #fastapi-dev } @@ -68,8 +121,8 @@ FastAPI CLI は、Python プログラムへのパス(例: `main.py`)を受 多くの場合(そして推奨されるのは)、上位に HTTPS を終端する「termination proxy」を置きます。これはアプリのデプロイ方法に依存し、プロバイダが代行する場合もあれば、自分で設定する必要がある場合もあります。 -/// tip | 豆知識 +/// tip -詳しくは、[デプロイのドキュメント](deployment/index.md){.internal-link target=_blank}を参照してください。 +詳しくは、[デプロイのドキュメント](deployment/index.md)を参照してください。 /// diff --git a/docs/ja/docs/features.md b/docs/ja/docs/features.md index 40a1d2e60d..cfde6592d2 100644 --- a/docs/ja/docs/features.md +++ b/docs/ja/docs/features.md @@ -6,8 +6,8 @@ ### オープンスタンダード準拠 { #based-on-open-standards } -* API 作成のための OpenAPIpath operations、パラメータ、リクエストボディ、セキュリティなどの宣言を含みます。 -* JSON Schema によるデータモデルの自動ドキュメント化(OpenAPI 自体が JSON Schema に基づいています)。 +* API 作成のための [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification)。パス オペレーション、パラメータ、リクエストボディ、セキュリティなどの宣言を含みます。 +* [**JSON Schema**](https://json-schema.org/) によるデータモデルの自動ドキュメント化(OpenAPI 自体が JSON Schema に基づいています)。 * 入念な調査のうえ、これらの標準を中心に設計されています。後付けのレイヤーではありません。 * これにより、多くの言語で自動 **クライアントコード生成** が可能です。 @@ -15,11 +15,11 @@ 対話的な API ドキュメントと探索的な Web ユーザーインターフェース。フレームワークは OpenAPI に基づいているため、複数のオプションがあり、デフォルトで 2 つ含まれます。 -* Swagger UI。インタラクティブに探索しつつ、ブラウザから直接 API を呼び出してテストできます。 +* [**Swagger UI**](https://github.com/swagger-api/swagger-ui)。インタラクティブに探索しつつ、ブラウザから直接 API を呼び出してテストできます。 ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* ReDoc による代替の API ドキュメント。 +* [**ReDoc**](https://github.com/Rebilly/ReDoc) による代替の API ドキュメント。 ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) @@ -27,7 +27,7 @@ すべて標準の **Python の型** 宣言(Pydantic に感謝)に基づいています。新しい構文を学ぶ必要はありません。標準的でモダンな Python だけです。 -(FastAPI を使わない場合でも)Python の型の使い方を 2 分で復習したい場合は、短いチュートリアル [Python Types](python-types.md){.internal-link target=_blank} を参照してください。 +(FastAPI を使わない場合でも)Python の型の使い方を 2 分で復習したい場合は、短いチュートリアル [Python の型](python-types.md) を参照してください。 型を使った標準的な Python を記述します: @@ -36,13 +36,13 @@ from datetime import date from pydantic import BaseModel -# 変数を str として宣言 -# そして関数内でエディタ支援を受ける +# Declare a variable as a str +# and get editor support inside the function def main(user_id: str): return user_id -# Pydantic モデル +# A Pydantic model class User(BaseModel): id: int name: str @@ -75,7 +75,7 @@ my_second_user: User = User(**second_user_data) フレームワーク全体が使いやすく直感的になるよう設計されており、最高の開発体験を確保するため、開発開始前から複数のエディタであらゆる判断が検証されています。 -Python 開発者調査では、最もよく使われる機能の 1 つが「オートコンプリート」であることが明らかです。 +Python 開発者調査では、[最もよく使われる機能の 1 つが「オートコンプリート」であることが明らかです](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features)。 **FastAPI** はその要求を満たすことを基盤にしています。オートコンプリートはどこでも機能します。 @@ -83,11 +83,11 @@ Python 開発者調査では、Visual Studio Code の場合: +* [Visual Studio Code](https://code.visualstudio.com/) の場合: ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -* PyCharm の場合: +* [PyCharm](https://www.jetbrains.com/pycharm/) の場合: ![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) @@ -124,7 +124,7 @@ Python 開発者調査では、Starlette と完全に互換性があり(かつそれに基づいています)。そのため、手元の Starlette の追加コードも動作します。 +**FastAPI** は [**Starlette**](https://www.starlette.dev/) と完全に互換性があり(かつそれに基づいています)。そのため、手元の Starlette の追加コードも動作します。 `FastAPI` は実際には `Starlette` のサブクラスです。すでに Starlette を知っている、あるいは使っているなら、ほとんどの機能は同じように動作します。 **FastAPI** では **Starlette** のすべての機能が利用できます(FastAPI は強化された Starlette にすぎません): -* 圧倒的なパフォーマンス。利用可能な最速クラスの Python フレームワークの 1 つで、**NodeJS** や **Go** と同等です。 +* 圧倒的なパフォーマンス。[利用可能な最速クラスの Python フレームワークの 1 つで、**NodeJS** や **Go** と同等です](https://github.com/encode/starlette#performance)。 * **WebSocket** のサポート。 * プロセス内バックグラウンドタスク。 * 起動およびシャットダウンイベント。 @@ -177,7 +177,7 @@ FastAPI には、非常に使いやすく、かつ非常に強力な Pydantic と完全に互換性があり(かつそれに基づいています)。そのため、手元の Pydantic の追加コードも動作します。 +**FastAPI** は [**Pydantic**](https://docs.pydantic.dev/) と完全に互換性があり(かつそれに基づいています)。そのため、手元の Pydantic の追加コードも動作します。 Pydantic に基づく外部ライブラリ(データベース用の ORMODM など)も含まれます。 diff --git a/docs/ja/docs/help-fastapi.md b/docs/ja/docs/help-fastapi.md index ed91bb19f6..3ae18449fa 100644 --- a/docs/ja/docs/help-fastapi.md +++ b/docs/ja/docs/help-fastapi.md @@ -12,7 +12,7 @@ FastAPIや他のユーザー、作者を応援したいですか? ## ニュースレターを購読 { #subscribe-to-the-newsletter } -[**FastAPI and friends** ニュースレター](newsletter.md){.internal-link target=_blank}(配信はまれです)を購読すると、次の情報をキャッチアップできます: +[**FastAPI and friends** ニュースレター](newsletter.md)(配信はまれです)を購読すると、次の情報をキャッチアップできます: * FastAPI と関連プロジェクトのニュース 🚀 * ガイド 📝 @@ -22,17 +22,17 @@ FastAPIや他のユーザー、作者を応援したいですか? ## X (Twitter) で FastAPI をフォロー { #follow-fastapi-on-x-twitter } -**X (Twitter)** で @fastapi をフォローして、**FastAPI** の最新情報を受け取りましょう。🐦 +[**X (Twitter)** で @fastapi をフォロー](https://x.com/fastapi)して、**FastAPI** の最新情報を受け取りましょう。🐦 ## GitHubで **FastAPI** にStar { #star-fastapi-in-github } -GitHubでFastAPIに「Star」をつけることができます(右上部のStarボタンをクリック): https://github.com/fastapi/fastapi。⭐️ +GitHubでFastAPIに「Star」をつけることができます(右上部のStarボタンをクリック): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi)。⭐️ スターを増やすことで、他のユーザーの目につきやすくなり、すでに多くの人の役に立っていることが伝わります。 ## GitHubレポジトリのリリースをWatch { #watch-the-github-repository-for-releases } -GitHubでFastAPIを「Watch」できます(右上部の「Watch」ボタンをクリック): https://github.com/fastapi/fastapi。👀 +GitHubでFastAPIを「Watch」できます(右上部の「Watch」ボタンをクリック): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi)。👀 そこで「Releases only」を選択できます。 @@ -40,45 +40,45 @@ GitHubでFastAPIを「Watch」できます(右上部の「Watch」ボタンを ## 開発者とつながる { #connect-with-the-author } -作者である私(Sebastián Ramírez / `tiangolo`)とつながれます。 +作者である[私(Sebastián Ramírez / `tiangolo`)](https://tiangolo.com)とつながれます。 できること: -* **GitHub** でフォロー。 +* [**GitHub** でフォロー](https://github.com/tiangolo)。 * 役に立つかもしれない、私が作成した他のオープンソースプロジェクトを見られます。 * 新しいオープンソースプロジェクトを作成したときにわかります。 -* **X (Twitter)** でフォロー または Mastodon。 +* [**X (Twitter)** でフォロー](https://x.com/tiangolo) または [Mastodon](https://fosstodon.org/@tiangolo)。 * あなたがどのようにFastAPIを使っているか教えてください(聞けると嬉しいです)。 * 新しいツールの告知やリリースを聞けます。 - * さらに、X (Twitter) の @fastapi(別アカウント)もフォローできます。 -* **LinkedIn** でフォロー。 + * さらに、[X (Twitter) の @fastapi](https://x.com/fastapi)(別アカウント)もフォローできます。 +* [**LinkedIn** でフォロー](https://www.linkedin.com/in/tiangolo/)。 * 新しいツールの告知やリリースを聞けます(ただしX (Twitter) の方をよく使っています 🤷‍♂)。 -* **Dev.to****Medium** で執筆内容を読む(またはフォロー)。 +* [**Dev.to**](https://dev.to/tiangolo) や [**Medium**](https://medium.com/@tiangolo) で執筆内容を読む(またはフォロー)。 * 私のアイデアや、作成したツールに関する記事を読めます。 * 新しい記事を公開したときに読めます。 ## **FastAPI** についてツイート { #tweet-about-fastapi } -**FastAPI** についてツイートして、なぜ気に入っているのかを私や他の人に教えてください。🎉 +[**FastAPI** についてツイート](https://x.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi)して、なぜ気に入っているのかを私や他の人に教えてください。🎉 **FastAPI** がどのように使われているか、どこを気に入っているか、どのプロジェクト/会社で使っているか等、聞けると嬉しいです。 ## FastAPIに投票 { #vote-for-fastapi } -* Slantで **FastAPI** に投票。 -* AlternativeToで **FastAPI** に投票。 -* StackShare で **FastAPI** を使っていると宣言。 +* [Slantで **FastAPI** に投票](https://www.slant.co/options/34241/~fastapi-review)。 +* [AlternativeToで **FastAPI** に投票](https://alternativeto.net/software/fastapi/about/)。 +* [StackShare で **FastAPI** を使っていると宣言](https://stackshare.io/pypi-fastapi)。 ## GitHubで質問に困っている人を助ける { #help-others-with-questions-in-github } 次の場所で、他の人の質問を手助けできます: -* GitHub Discussions -* GitHub Issues +* [GitHub Discussions](https://github.com/fastapi/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered) +* [GitHub Issues](https://github.com/fastapi/fastapi/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Aquestion+-label%3Aanswered+) 多くの場合、その質問の答えをすでに知っているかもしれません。🤓 -もし多くの人の質問に答えて助けてくれたなら、あなたは公式の[FastAPI Expert](fastapi-people.md#fastapi-experts){.internal-link target=_blank}になります。🎉 +もし多くの人の質問に答えて助けてくれたなら、あなたは公式の[FastAPI Expert](fastapi-people.md#fastapi-experts)になります。🎉 最も大事なポイントは「親切であること」を心がけることです。人はフラストレーションを抱えてやって来るので、必ずしも最良の聞き方をしているとは限りませんが、できる限り親切に対応しましょう。🤗 @@ -98,13 +98,13 @@ GitHubでFastAPIを「Watch」できます(右上部の「Watch」ボタンを * 質問が理解できない場合は、さらに「詳細」を尋ねます。 -### 問題を再現する { #reproduce-the-problem } +### 问題を再現する { #reproduce-the-problem } 多くのケースや質問は、その人の「元のコード」に関係しています。 しばしばコードの断片だけが共有されますが、それでは問題を「再現」するには不十分です。 -* ローカルで同じエラーや挙動を確認できるように、またはユースケースをよりよく理解できるように、**コピー&ペースト**して実行できる最小の再現可能な例の提供を依頼できます。 +* ローカルで同じエラーや挙動を確認できるように、またはユースケースをよりよく理解できるように、**コピー&ペースト**して実行できる[最小の再現可能な例](https://stackoverflow.com/help/minimal-reproducible-example)の提供を依頼できます。 * とても寛大な気分なら、問題の説明だけをもとに、あなた自身でそのような**例を作成**してみることもできます。ただし時間がかかる可能性が高いので、まずは問題の明確化を依頼した方が良い場合もあります。 @@ -125,7 +125,7 @@ GitHubでFastAPIを「Watch」できます(右上部の「Watch」ボタンを ## GitHubレポジトリをWatch { #watch-the-github-repository } -GitHubでFastAPIを「Watch」できます(右上部の「Watch」ボタンをクリック): https://github.com/fastapi/fastapi。👀 +GitHubでFastAPIを「Watch」できます(右上部の「Watch」ボタンをクリック): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi)。👀 「Releases only」ではなく「Watching」を選択すると、新しい issue や質問が作成されたときに通知を受け取れます。新しい issue のみ、Discussions のみ、PR のみ、など通知対象を絞ることもできます。 @@ -133,7 +133,7 @@ GitHubでFastAPIを「Watch」できます(右上部の「Watch」ボタンを ## 質問する { #ask-questions } -GitHubレポジトリで新しい質問を作成できます。例えば: +GitHubレポジトリで[新しい質問](https://github.com/fastapi/fastapi/discussions/new?category=questions)を作成できます。例えば: * **質問**をする、または**問題**について尋ねる。 * 新しい**機能**を提案する。 @@ -196,12 +196,12 @@ GitHubレポジトリでこのファイルを編集して共有。 +* 自分が作成/発見した FastAPI に関する記事・動画・ポッドキャストを、[このファイルを編集](https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml)して共有。 * 該当セクションの先頭にリンクを追加してください。 -* 自分の言語への[ドキュメント翻訳を手伝う](contributing.md#translations){.internal-link target=_blank}。 +* 自分の言語への[ドキュメント翻訳を手伝う](contributing.md#translations)。 * 他の人が作成した翻訳のレビューも手伝えます。 * 新しいドキュメントセクションの提案。 * 既存のissue/バグの修正。 @@ -218,8 +218,8 @@ GitHubレポジトリでDiscord チャットサーバー 👥 に参加し、FastAPI コミュニティのみんなと交流しましょう。 +👥 [Discord チャットサーバー](https://discord.gg/VQjSZaeJmf) 👥 に参加し、FastAPI コミュニティのみんなと交流しましょう。 /// tip | 豆知識 -質問は GitHub Discussions に投稿してください。そこなら[FastAPI Experts](fastapi-people.md#fastapi-experts){.internal-link target=_blank}から助けてもらえる可能性がずっと高いです。 +質問は [GitHub Discussions](https://github.com/fastapi/fastapi/discussions/new?category=questions) に投稿してください。そこなら[FastAPI Experts](fastapi-people.md#fastapi-experts)から助けてもらえる可能性がずっと高いです。 チャットは一般的な会話のみに使いましょう。 @@ -243,13 +243,13 @@ GitHubレポジトリでGitHub sponsors を通じて作者(私)を支援できます。プランに応じて、ドキュメントにバッジが表示されるなどの特典がある場合があります。🎁 +あなたの**製品/会社**が **FastAPI** に依存している、または関連しており、そのユーザーにリーチしたい場合は、[GitHub sponsors](https://github.com/sponsors/tiangolo) を通じて作者(私)を支援できます。プランに応じて、ドキュメントにバッジが表示されるなどの特典がある場合があります。🎁 --- diff --git a/docs/ja/docs/history-design-future.md b/docs/ja/docs/history-design-future.md index 1465557080..8364002886 100644 --- a/docs/ja/docs/history-design-future.md +++ b/docs/ja/docs/history-design-future.md @@ -1,6 +1,6 @@ # 歴史、設計、そしてこれから { #history-design-and-future } -少し前に、**FastAPI**のユーザーに以下の様に尋ねられました: +しばらく前に、[ある **FastAPI** ユーザーが質問しました](https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920): > このプロジェクトの歴史は?何もないところから、数週間ですごいものができているようです。 [...] @@ -14,7 +14,7 @@ **FastAPI** の歴史は、その前身の歴史が大部分を占めています。 -[代替ツールから受けたインスピレーションと比較](alternatives.md){.internal-link target=_blank}のセクションでこう述べています: +[代替手段](alternatives.md)のセクションでこう述べています:
@@ -44,7 +44,7 @@ もっとも人気のあるPythonエディターでいくつかのアイデアをテストしました。PyCharm、VS Code、Jediベースのエディターです。 -最新の Python開発者調査で、それらのエディターがユーザーの80%をカバーしていました。 +最新の [Python開発者調査](https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools)で、それらのエディターがユーザーの80%をカバーしていました。 これは、**FastAPI**がPython開発者の80%が使用しているエディターで特別にテストされたことを意味します。また、ほとんどの他のエディターも同様に動作する傾向があるため、この恩恵は事実上すべてのエディターでうけられるはずです。 @@ -54,11 +54,11 @@ ## 要件 { #requirements } -いくつかの代替手法を試したあと、私は**Pydantic**の強みを利用することを決めました。 +いくつかの代替手法を試したあと、私は[**Pydantic**](https://docs.pydantic.dev/)の強みを利用することを決めました。 そして、JSON Schemaに完全に準拠するようにしたり、制約宣言を定義するさまざまな方法をサポートしたり、いくつかのエディターでのテストに基づいてエディターのサポート (型チェック、自動補完) を改善するために貢献しました。 -開発中、もう1つの重要な鍵となる**Starlette**にも貢献しました。 +開発中、もう1つの重要な鍵となる[**Starlette**](https://www.starlette.dev/)にも貢献しました。 ## 開発 { #development } @@ -76,4 +76,4 @@ **FastAPI**には大きな未来が待っています。 -そして、[あなたの助け](help-fastapi.md){.internal-link target=_blank}を大いに歓迎します。 +そして、[あなたの助け](help-fastapi.md)を大いに歓迎します。 diff --git a/docs/ja/docs/how-to/authentication-error-status-code.md b/docs/ja/docs/how-to/authentication-error-status-code.md index 9bef476444..ec5e25b75b 100644 --- a/docs/ja/docs/how-to/authentication-error-status-code.md +++ b/docs/ja/docs/how-to/authentication-error-status-code.md @@ -2,7 +2,7 @@ FastAPI バージョン `0.122.0` より前は、統合されたセキュリティユーティリティが認証に失敗してクライアントへエラーを返す際、HTTP ステータスコード `403 Forbidden` を使用していました。 -FastAPI バージョン `0.122.0` 以降では、より適切な HTTP ステータスコード `401 Unauthorized` を使用し、HTTP 仕様に従ってレスポンスに妥当な `WWW-Authenticate` ヘッダーを含めます。RFC 7235RFC 9110。 +FastAPI バージョン `0.122.0` 以降では、より適切な HTTP ステータスコード `401 Unauthorized` を使用し、HTTP 仕様に従ってレスポンスに妥当な `WWW-Authenticate` ヘッダーを含めます。[RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-3.1), [RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized)。 しかし、何らかの理由でクライアントが従来の挙動に依存している場合は、セキュリティクラスでメソッド `make_not_authenticated_error` をオーバーライドすることで、その挙動に戻せます。 diff --git a/docs/ja/docs/how-to/conditional-openapi.md b/docs/ja/docs/how-to/conditional-openapi.md index 0febe1ef67..b6281ed06f 100644 --- a/docs/ja/docs/how-to/conditional-openapi.md +++ b/docs/ja/docs/how-to/conditional-openapi.md @@ -10,7 +10,7 @@ もしセキュリティ上の欠陥がソースコードにあるならば、それは存在したままです。 -ドキュメンテーションを非表示にするのは、単にあなたのAPIへのアクセス方法を難解にするだけでなく、同時にあなた自身の本番環境でのAPIのデバッグを困難にしてしまう可能性があります。単純に、 秘匿によるセキュリティ の一つの形態として考えられるでしょう。 +ドキュメンテーションを非表示にするのは、単にあなたのAPIへのアクセス方法を難解にするだけでなく、同時にあなた自身の本番環境でのAPIのデバッグを困難にしてしまう可能性があります。単純に、[秘匿によるセキュリティ](https://en.wikipedia.org/wiki/Security_through_obscurity) の一つの形態として考えられるでしょう。 もしあなたのAPIのセキュリティを強化したいなら、いくつかのよりよい方法があります。例を示すと、 diff --git a/docs/ja/docs/how-to/configure-swagger-ui.md b/docs/ja/docs/how-to/configure-swagger-ui.md index 8be7adc84c..2950918575 100644 --- a/docs/ja/docs/how-to/configure-swagger-ui.md +++ b/docs/ja/docs/how-to/configure-swagger-ui.md @@ -1,6 +1,6 @@ # Swagger UI の設定 { #configure-swagger-ui } -いくつかの追加の Swagger UI パラメータを設定できます。 +いくつかの追加の [Swagger UI パラメータ](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/)を設定できます。 設定するには、`FastAPI()` のアプリオブジェクトを作成するとき、または `get_swagger_ui_html()` 関数に `swagger_ui_parameters` 引数を渡します。 @@ -50,7 +50,7 @@ FastAPI には、多くのユースケースに適した既定の設定パラメ ## その他の Swagger UI パラメータ { #other-swagger-ui-parameters } -利用可能な他のすべての設定については、公式の Swagger UI パラメータのドキュメントを参照してください。 +利用可能な他のすべての設定については、公式の [Swagger UI パラメータのドキュメント](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/)を参照してください。 ## JavaScript 専用の設定 { #javascript-only-settings } diff --git a/docs/ja/docs/how-to/custom-docs-ui-assets.md b/docs/ja/docs/how-to/custom-docs-ui-assets.md index c0c9745b28..eb1b96c5af 100644 --- a/docs/ja/docs/how-to/custom-docs-ui-assets.md +++ b/docs/ja/docs/how-to/custom-docs-ui-assets.md @@ -54,7 +54,7 @@ Swagger UI がこの処理を裏側で行いますが、そのためにこの「 ### テスト { #test-it } -これで、http://127.0.0.1:8000/docs にアクセスしてページを再読み込みすると、新しい CDN からそれらのアセットが読み込まれるはずです。 +これで、[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) にアクセスしてページを再読み込みすると、新しい CDN からそれらのアセットが読み込まれるはずです。 ## ドキュメント用 JavaScript と CSS のセルフホスティング { #self-hosting-javascript-and-css-for-docs } @@ -93,12 +93,12 @@ Swagger UI がこの処理を裏側で行いますが、そのためにこの「 **Swagger UI** では次のファイルを使用します: -- `swagger-ui-bundle.js` -- `swagger-ui.css` +- [`swagger-ui-bundle.js`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js) +- [`swagger-ui.css`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css) そして **ReDoc** では次のファイルを使用します: -- `redoc.standalone.js` +- [`redoc.standalone.js`](https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js) その後、ファイル構成は次のようになります: @@ -122,7 +122,7 @@ Swagger UI がこの処理を裏側で行いますが、そのためにこの「 ### 静的ファイルのテスト { #test-the-static-files } -アプリケーションを起動し、http://127.0.0.1:8000/static/redoc.standalone.js にアクセスします。 +アプリケーションを起動し、[http://127.0.0.1:8000/static/redoc.standalone.js](http://127.0.0.1:8000/static/redoc.standalone.js) にアクセスします。 **ReDoc** 用の非常に長い JavaScript ファイルが表示されるはずです。 @@ -180,6 +180,6 @@ Swagger UI がこの処理を裏側で行いますが、そのためにこの「 ### 静的ファイル UI のテスト { #test-static-files-ui } -これで、WiFi を切断して http://127.0.0.1:8000/docs にアクセスし、ページを再読み込みできるはずです。 +これで、WiFi を切断して [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) にアクセスし、ページを再読み込みできるはずです。 インターネットに接続していなくても、API のドキュメントを表示し、API と対話できます。 diff --git a/docs/ja/docs/how-to/custom-request-and-route.md b/docs/ja/docs/how-to/custom-request-and-route.md index ae64f31097..d2b0806e44 100644 --- a/docs/ja/docs/how-to/custom-request-and-route.md +++ b/docs/ja/docs/how-to/custom-request-and-route.md @@ -18,7 +18,7 @@ FastAPI を始めたばかりの場合は、このセクションは読み飛ば ユースケースの例: -* JSON ではないリクエストボディを JSON に変換する(例: `msgpack`)。 +* JSON ではないリクエストボディを JSON に変換する(例: [`msgpack`](https://msgpack.org/index.html))。 * gzip 圧縮されたリクエストボディの解凍。 * すべてのリクエストボディの自動ロギング。 @@ -32,7 +32,7 @@ gzip のリクエストを解凍するために、カスタムの `Request` サ /// tip | 豆知識 -これは仕組みを示すためのサンプルです。Gzip 対応が必要な場合は、用意されている [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank} を使用できます。 +これは仕組みを示すためのサンプルです。Gzip 対応が必要な場合は、用意されている [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware) を使用できます。 /// @@ -66,7 +66,7 @@ gzip のリクエストを解凍するために、カスタムの `Request` サ そしてこの 2 つ(`scope` と `receive`)が、新しい `Request` インスタンスを作成するために必要なものです。 -`Request` について詳しくは、Starlette の Requests に関するドキュメント を参照してください。 +`Request` について詳しくは、[Starlette の Requests に関するドキュメント](https://www.starlette.dev/requests/) を参照してください。 /// @@ -82,7 +82,7 @@ gzip のリクエストを解凍するために、カスタムの `Request` サ /// tip | 豆知識 -同じ問題を解決するには、`RequestValidationError` 用のカスタムハンドラで `body` を使う方がずっと簡単でしょう([エラー処理](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank})。 +同じ問題を解決するには、`RequestValidationError` 用のカスタムハンドラで `body` を使う方がずっと簡単でしょう([エラー処理](../tutorial/handling-errors.md#use-the-requestvalidationerror-body))。 ただし、この例も有効で、内部コンポーネントとどのようにやり取りするかを示しています。 diff --git a/docs/ja/docs/how-to/extending-openapi.md b/docs/ja/docs/how-to/extending-openapi.md index df5b3cd35a..e9ef9923fd 100644 --- a/docs/ja/docs/how-to/extending-openapi.md +++ b/docs/ja/docs/how-to/extending-openapi.md @@ -37,7 +37,7 @@ 上記の情報を使って、同じユーティリティ関数で OpenAPI スキーマを生成し、必要な部分を上書きできます。 -たとえば、カスタムロゴを含めるための ReDoc の OpenAPI 拡張を追加してみましょう。 +たとえば、[カスタムロゴを含めるための ReDoc の OpenAPI 拡張](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo)を追加してみましょう。 ### 通常の **FastAPI** { #normal-fastapi } @@ -75,6 +75,6 @@ OpenAPI スキーマの `info`「オブジェクト」にカスタムの `x-logo ### 確認 { #check-it } -http://127.0.0.1:8000/redoc にアクセスすると、カスタムロゴ(この例では **FastAPI** のロゴ)が使われていることが確認できます: +[http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) にアクセスすると、カスタムロゴ(この例では **FastAPI** のロゴ)が使われていることが確認できます: diff --git a/docs/ja/docs/how-to/general.md b/docs/ja/docs/how-to/general.md index 8879c68eb9..ca2de8f3fb 100644 --- a/docs/ja/docs/how-to/general.md +++ b/docs/ja/docs/how-to/general.md @@ -4,36 +4,40 @@ ## データのフィルタリング - セキュリティ { #filter-data-security } -返すべき以上のデータを返さないようにするには、[チュートリアル - レスポンスモデル - 戻り値の型](../tutorial/response-model.md){.internal-link target=_blank} を参照してください。 +返すべき以上のデータを返さないようにするには、[チュートリアル - レスポンスモデル - 戻り値の型](../tutorial/response-model.md) を参照してください。 + +## レスポンス性能の最適化 - レスポンスモデル - 戻り値の型 { #optimize-response-performance-response-model-return-type } + +JSON データを返す際の性能を最適化するには、戻り値の型またはレスポンスモデルを使用してください。そうすることで、Pydantic が Python を経由せずに Rust 側で JSON へのシリアライズを処理します。詳細は [チュートリアル - レスポンスモデル - 戻り値の型](../tutorial/response-model.md) を参照してください。 ## ドキュメントのタグ - OpenAPI { #documentation-tags-openapi } -*path operations* にタグを追加し、ドキュメント UI でグループ化するには、[チュートリアル - path operation の設定 - タグ](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank} を参照してください。 +*path operations* にタグを追加し、ドキュメント UI でグループ化するには、[チュートリアル - path operation の設定 - タグ](../tutorial/path-operation-configuration.md#tags) を参照してください。 ## ドキュメントの概要と説明 - OpenAPI { #documentation-summary-and-description-openapi } -*path operations* に概要と説明を追加し、ドキュメント UI に表示するには、[チュートリアル - path operation の設定 - 概要と説明](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank} を参照してください。 +*path operations* に概要と説明を追加し、ドキュメント UI に表示するには、[チュートリアル - path operation の設定 - 概要と説明](../tutorial/path-operation-configuration.md#summary-and-description) を参照してください。 ## ドキュメントのレスポンス説明 - OpenAPI { #documentation-response-description-openapi } -ドキュメント UI に表示されるレスポンスの説明を定義するには、[チュートリアル - path operation の設定 - レスポンスの説明](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank} を参照してください。 +ドキュメント UI に表示されるレスポンスの説明を定義するには、[チュートリアル - path operation の設定 - レスポンスの説明](../tutorial/path-operation-configuration.md#response-description) を参照してください。 ## *Path Operation* の非推奨化 - OpenAPI { #documentation-deprecate-a-path-operation-openapi } -*path operation* を非推奨にし、ドキュメント UI に表示するには、[チュートリアル - path operation の設定 - 非推奨](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank} を参照してください。 +*path operation* を非推奨にし、ドキュメント UI に表示するには、[チュートリアル - path operation の設定 - 非推奨](../tutorial/path-operation-configuration.md#deprecate-a-path-operation) を参照してください。 ## 任意のデータを JSON 互換に変換 { #convert-any-data-to-json-compatible } -任意のデータを JSON 互換に変換するには、[チュートリアル - JSON 互換エンコーダ](../tutorial/encoder.md){.internal-link target=_blank} を参照してください。 +任意のデータを JSON 互換に変換するには、[チュートリアル - JSON 互換エンコーダ](../tutorial/encoder.md) を参照してください。 ## OpenAPI メタデータ - ドキュメント { #openapi-metadata-docs } -ライセンス、バージョン、連絡先などを含むメタデータを OpenAPI スキーマに追加するには、[チュートリアル - メタデータとドキュメントの URL](../tutorial/metadata.md){.internal-link target=_blank} を参照してください。 +ライセンス、バージョン、連絡先などを含むメタデータを OpenAPI スキーマに追加するには、[チュートリアル - メタデータとドキュメントの URL](../tutorial/metadata.md) を参照してください。 ## OpenAPI のカスタム URL { #openapi-custom-url } -OpenAPI の URL をカスタマイズ(または削除)するには、[チュートリアル - メタデータとドキュメントの URL](../tutorial/metadata.md#openapi-url){.internal-link target=_blank} を参照してください。 +OpenAPI の URL をカスタマイズ(または削除)するには、[チュートリアル - メタデータとドキュメントの URL](../tutorial/metadata.md#openapi-url) を参照してください。 ## OpenAPI ドキュメントの URL { #openapi-docs-urls } -自動生成されるドキュメント UI が使用する URL を変更するには、[チュートリアル - メタデータとドキュメントの URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank} を参照してください。 +自動生成されるドキュメント UI が使用する URL を変更するには、[チュートリアル - メタデータとドキュメントの URL](../tutorial/metadata.md#docs-urls) を参照してください。 diff --git a/docs/ja/docs/how-to/graphql.md b/docs/ja/docs/how-to/graphql.md index bd0d223498..d1356b59a9 100644 --- a/docs/ja/docs/how-to/graphql.md +++ b/docs/ja/docs/how-to/graphql.md @@ -18,18 +18,18 @@ **ASGI** をサポートする **GraphQL** ライブラリの一部を以下に示します。**FastAPI** と組み合わせて使用できます: -* Strawberry 🍓 - * FastAPI 向けドキュメントあり -* Ariadne - * FastAPI 向けドキュメントあり -* Tartiflette - * ASGI 連携用の Tartiflette ASGI あり -* Graphene - * starlette-graphene3 あり +* [Strawberry](https://strawberry.rocks/) 🍓 + * [FastAPI 向けドキュメント](https://strawberry.rocks/docs/integrations/fastapi)あり +* [Ariadne](https://ariadnegraphql.org/) + * [FastAPI 向けドキュメント](https://ariadnegraphql.org/docs/fastapi-integration)あり +* [Tartiflette](https://tartiflette.io/) + * ASGI 連携用の [Tartiflette ASGI](https://tartiflette.github.io/tartiflette-asgi/) あり +* [Graphene](https://graphene-python.org/) + * [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3) あり ## Strawberry で GraphQL { #graphql-with-strawberry } -**GraphQL** が必要、または利用したい場合は、**Strawberry** を**推奨**します。**FastAPI** の設計に最も近く、すべてが**型アノテーション**に基づいています。 +**GraphQL** が必要、または利用したい場合は、[**Strawberry**](https://strawberry.rocks/) を**推奨**します。**FastAPI** の設計に最も近く、すべてが**型アノテーション**に基づいています。 ユースケースによっては他のライブラリを選ぶ方がよい場合もありますが、私に尋ねられれば、おそらく **Strawberry** を試すことを勧めるでしょう。 @@ -37,24 +37,24 @@ FastAPI と Strawberry を統合する方法の簡単なプレビューです: {* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} -詳細は Strawberry のドキュメントをご覧ください。 +詳細は [Strawberry のドキュメント](https://strawberry.rocks/)をご覧ください。 -また、Strawberry と FastAPI の連携に関するドキュメントもあります。 +また、[Strawberry と FastAPI](https://strawberry.rocks/docs/integrations/fastapi) の連携に関するドキュメントもあります。 ## Starlette の旧 `GraphQLApp` { #older-graphqlapp-from-starlette } -以前の Starlette には、Graphene と統合するための `GraphQLApp` クラスが含まれていました。 +以前の Starlette には、[Graphene](https://graphene-python.org/) と統合するための `GraphQLApp` クラスが含まれていました。 -これは Starlette からは非推奨になりましたが、もしそれを使用しているコードがある場合は、同じユースケースをカバーし、**ほぼ同一のインターフェース**を持つ starlette-graphene3 へ容易に**移行**できます。 +これは Starlette からは非推奨になりましたが、もしそれを使用しているコードがある場合は、同じユースケースをカバーし、**ほぼ同一のインターフェース**を持つ [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3) へ容易に**移行**できます。 /// tip | 豆知識 -GraphQL が必要であれば、依然として Strawberry の利用を推奨します。独自のクラスや型ではなく、型アノテーションに基づいているためです。 +GraphQL が必要であれば、依然として [Strawberry](https://strawberry.rocks/) の利用を推奨します。独自のクラスや型ではなく、型アノテーションに基づいているためです。 /// ## さらに学ぶ { #learn-more } -**GraphQL** については、公式 GraphQL ドキュメントでさらに学べます。 +**GraphQL** については、[公式 GraphQL ドキュメント](https://graphql.org/)でさらに学べます。 上記の各ライブラリについては、リンク先のドキュメントをご参照ください。 diff --git a/docs/ja/docs/how-to/index.md b/docs/ja/docs/how-to/index.md index b1cd177852..9d9348abfc 100644 --- a/docs/ja/docs/how-to/index.md +++ b/docs/ja/docs/how-to/index.md @@ -8,6 +8,6 @@ /// tip | 豆知識 -**FastAPI を学ぶ**ことを体系的に進めたい場合(推奨)、代わりに [チュートリアル - ユーザーガイド](../tutorial/index.md){.internal-link target=_blank} を章ごとに読んでください。 +**FastAPI を学ぶ**ことを体系的に進めたい場合(推奨)、代わりに [チュートリアル - ユーザーガイド](../tutorial/index.md) を章ごとに読んでください。 /// diff --git a/docs/ja/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/ja/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index f1414ac281..320be14443 100644 --- a/docs/ja/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/ja/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -22,7 +22,7 @@ Python の最新機能を使いたい場合は、Pydantic v2 を使用してい ## 公式ガイド { #official-guide } -Pydantic には v1 から v2 への公式の 移行ガイド があります。 +Pydantic には v1 から v2 への公式の [移行ガイド](https://docs.pydantic.dev/latest/migration/) があります。 変更点、検証がより正確で厳密になった点、注意事項などが含まれます。 @@ -30,7 +30,7 @@ Pydantic には v1 から v2 への公式の `bump-pydantic` を使用できます。 +同じ Pydantic チームが提供する [`bump-pydantic`](https://github.com/pydantic/bump-pydantic) を使用できます。 このツールは必要なコード変更のほとんどを自動で行います。 @@ -88,7 +88,7 @@ graph TB style V2Field fill:#f9fff3 ``` -...but, you can have separated models using Pydantic v1 and v2 in the same app. +...しかし、同じアプリ内で Pydantic v1 と v2 を別々のモデルとして分けて使うことは可能です。 ```mermaid graph TB diff --git a/docs/ja/docs/how-to/testing-database.md b/docs/ja/docs/how-to/testing-database.md index af9ad75090..76d448e02a 100644 --- a/docs/ja/docs/how-to/testing-database.md +++ b/docs/ja/docs/how-to/testing-database.md @@ -1,7 +1,7 @@ # データベースのテスト { #testing-a-database } -データベース、SQL、SQLModel については、SQLModel ドキュメントで学べます。🤓 +データベース、SQL、SQLModel については、[SQLModel ドキュメント](https://sqlmodel.tiangolo.com/)で学べます。🤓 -FastAPI と一緒に SQLModel を使うためのミニ チュートリアルがあります。✨ +FastAPI と一緒に SQLModel を使うためのミニ [チュートリアル](https://sqlmodel.tiangolo.com/tutorial/fastapi/)があります。✨ -そのチュートリアルには、SQL データベースのテストに関するセクションも含まれています。😎 +そのチュートリアルには、[SQL データベースのテスト](https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/)に関するセクションも含まれています。😎 diff --git a/docs/ja/docs/index.md b/docs/ja/docs/index.md index 90368b4ae3..a8b9741985 100644 --- a/docs/ja/docs/index.md +++ b/docs/ja/docs/index.md @@ -11,25 +11,25 @@ FastAPI フレームワーク、高パフォーマンス、学びやすい、素早くコーディングできる、本番運用に対応

- + Test - + Coverage - + Package version - + Supported Python versions

--- -**ドキュメント**: https://fastapi.tiangolo.com +**ドキュメント**: [https://fastapi.tiangolo.com/ja](https://fastapi.tiangolo.com/ja) -**ソースコード**: https://github.com/fastapi/fastapi +**ソースコード**: [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi) --- @@ -44,7 +44,7 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP * **簡単**: 簡単に利用・習得できるようにデザインされています。ドキュメントを読む時間を削減します。 * **短い**: コードの重複を最小限にします。各パラメータ宣言から複数の機能を得られます。バグも減ります。 * **堅牢性**: 自動対話型ドキュメントにより、本番環境向けのコードが得られます。 -* **Standards-based**: API のオープンスタンダードに基づいており(そして完全に互換性があります)、OpenAPI(以前は Swagger として知られていました)や JSON Schema をサポートします。 +* **Standards-based**: API のオープンスタンダードに基づいており(そして完全に互換性があります)、[OpenAPI](https://github.com/OAI/OpenAPI-Specification)(以前は Swagger として知られていました)や [JSON Schema](https://json-schema.org/) をサポートします。 * 本番アプリケーションを構築している社内開発チームのテストに基づく見積もりです。 @@ -55,51 +55,51 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP ### Keystone Sponsor { #keystone-sponsor } {% for sponsor in sponsors.keystone -%} - + {% endfor -%} ### Gold and Silver Sponsors { #gold-and-silver-sponsors } {% for sponsor in sponsors.gold -%} - + {% endfor -%} {%- for sponsor in sponsors.silver -%} - + {% endfor %} -その他のスポンサー +[その他のスポンサー](https://fastapi.tiangolo.com/ja/fastapi-people/#sponsors) ## 評価 { #opinions } "_[...] 最近 **FastAPI** を使っています。 [...] 実際に私のチームの全ての **Microsoft の機械学習サービス** で使用する予定です。 そのうちのいくつかのコアな **Windows** 製品と **Office** 製品に統合されつつあります。_" -
Kabir Khan - Microsoft (ref)
+
Kabir Khan - Microsoft (ref)
--- "_FastAPIライブラリを採用し、クエリで **予測値** を取得できる **REST** サーバを構築しました。 [for Ludwig]_" -
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
+
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
--- "_**Netflix** は、**危機管理**オーケストレーションフレームワーク、**Dispatch** のオープンソースリリースを発表できることをうれしく思います。 [built with **FastAPI**]_" -
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
+
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
--- "_私は **FastAPI** にワクワクしています。 めちゃくちゃ楽しいです!_" -
Brian Okken - Python Bytes podcast host (ref)
+
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) podcast host (ref)
--- "_正直、あなたが作ったものは超堅実で洗練されているように見えます。いろんな意味で、それは私が **Hug** にそうなってほしかったものです。誰かがそれを作るのを見るのは本当に刺激的です。_" -
Timothy Crosley - Hug creator (ref)
+
Timothy Crosley - [Hug](https://github.com/hugapi/hug) creator (ref)
--- @@ -107,27 +107,27 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP "_私たちの **API** は **FastAPI** に切り替えました [...] きっと気に入ると思います [...]_" -
Ines Montani - Matthew Honnibal - Explosion AI founders - spaCy creators (ref) - (ref)
+
Ines Montani - Matthew Honnibal - [Explosion AI](https://explosion.ai) founders - [spaCy](https://spacy.io) creators (ref) - (ref)
--- "_本番運用の Python API を構築したい方には、**FastAPI** を強くおすすめします。**美しく設計**されており、**使いやすく**、**高いスケーラビリティ**があります。私たちの API ファースト開発戦略の **主要コンポーネント** となり、Virtual TAC Engineer などの多くの自動化やサービスを推進しています。_" -
Deon Pillsbury - Cisco (ref)
+
Deon Pillsbury - Cisco (ref)
--- ## FastAPI ミニドキュメンタリー { #fastapi-mini-documentary } -2025 年末に公開された FastAPI ミニドキュメンタリーがあります。オンラインで視聴できます: +2025 年末に公開された [FastAPI ミニドキュメンタリー](https://www.youtube.com/watch?v=mpR8ngthqiE)があります。オンラインで視聴できます: -FastAPI Mini Documentary +FastAPI Mini Documentary ## **Typer**、CLI 版 FastAPI { #typer-the-fastapi-of-clis } - + -Web API の代わりにターミナルで使用する CLI アプリを構築する場合は、**Typer** を確認してください。 +Web API の代わりにターミナルで使用する CLI アプリを構築する場合は、[**Typer**](https://typer.tiangolo.com/) を確認してください。 **Typer** は FastAPI の弟分です。そして、**CLI 版 FastAPI** を意図しています。 ⌨️ 🚀 @@ -135,12 +135,12 @@ Web API の代わりにターミナルで使用する Starlette -* データの部分は Pydantic +* [Starlette](https://www.starlette.dev/)(Web 部分) +* [Pydantic](https://docs.pydantic.dev/)(データ部分) ## インストール { #installation } -virtual environment を作成して有効化し、それから FastAPI をインストールします。 +[仮想環境](https://fastapi.tiangolo.com/ja/virtual-environments/) を作成して有効化し、それから FastAPI をインストールします。
@@ -199,7 +199,7 @@ async def read_item(item_id: int, q: str | None = None): **注**: -わからない場合は、ドキュメントの `async` と `await` の _"In a hurry?"_ セクションを確認してください。 +わからない場合は、_「In a hurry?」_ セクションの [ドキュメントの `async` と `await`](https://fastapi.tiangolo.com/ja/async/#in-a-hurry) を確認してください。 @@ -210,7 +210,7 @@ async def read_item(item_id: int, q: str | None = None):
```console -$ fastapi dev main.py +$ fastapi dev ╭────────── FastAPI CLI - Development mode ───────────╮ │ │ @@ -235,19 +235,19 @@ INFO: Application startup complete.
-fastapi dev main.py コマンドについて +fastapi dev コマンドについて -`fastapi dev` コマンドは `main.py` ファイルを読み取り、その中の **FastAPI** アプリを検出し、Uvicorn を使用してサーバーを起動します。 +`fastapi dev` コマンドは `main.py` ファイルを自動的に読み取り、その中の **FastAPI** アプリを検出し、[Uvicorn](https://www.uvicorn.dev) を使用してサーバーを起動します。 デフォルトでは、`fastapi dev` はローカル開発向けに自動リロードを有効にして起動します。 -詳しくは FastAPI CLI docs を参照してください。 +詳しくは [FastAPI CLI docs](https://fastapi.tiangolo.com/ja/fastapi-cli/) を参照してください。
### 動作確認 { #check-it } -ブラウザで http://127.0.0.1:8000/items/5?q=somequery を開きます。 +ブラウザで [http://127.0.0.1:8000/items/5?q=somequery](http://127.0.0.1:8000/items/5?q=somequery) を開きます。 以下の JSON のレスポンスが確認できます。 @@ -264,17 +264,17 @@ INFO: Application startup complete. ### 自動対話型 API ドキュメント { #interactive-api-docs } -次に、http://127.0.0.1:8000/docs にアクセスします。 +次に、[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) にアクセスします。 -自動対話型 API ドキュメントが表示されます(Swagger UI が提供しています)。 +自動対話型 API ドキュメントが表示されます([Swagger UI](https://github.com/swagger-api/swagger-ui) が提供しています)。 ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) ### 代替 API ドキュメント { #alternative-api-docs } -次に、http://127.0.0.1:8000/redoc にアクセスします。 +次に、[http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) にアクセスします。 -代替の自動ドキュメントが表示されます(ReDoc が提供しています)。 +代替の自動ドキュメントが表示されます([ReDoc](https://github.com/Rebilly/ReDoc) が提供しています)。 ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -316,7 +316,7 @@ def update_item(item_id: int, item: Item): ### 自動対話型 API ドキュメントのアップグレード { #interactive-api-docs-upgrade } -次に、http://127.0.0.1:8000/docs にアクセスします。 +次に、[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) にアクセスします。 * 自動対話型 API ドキュメントは新しいボディも含めて自動でアップデートされます。 @@ -332,7 +332,7 @@ def update_item(item_id: int, item: Item): ### 代替 API ドキュメントのアップグレード { #alternative-api-docs-upgrade } -次に、http://127.0.0.1:8000/redoc にアクセスします。 +次に、[http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) にアクセスします。 * 代替のドキュメントにも新しいクエリパラメータやボディが反映されます。 @@ -442,7 +442,7 @@ item: Item * 非常に強力で使いやすい **依存性注入** システム。 * **JWT トークン**を用いた **OAuth2** や **HTTP Basic** 認証のサポートを含む、セキュリティと認証。 * **深くネストされた JSON モデル**を宣言するための、より高度な(しかし同様に簡単な)手法(Pydantic のおかげです)。 -* Strawberry および他のライブラリによる **GraphQL** 統合。 +* [Strawberry](https://strawberry.rocks) および他のライブラリによる **GraphQL** 統合。 * 以下のようなたくさんのおまけ機能(Starlette のおかげです): * **WebSockets** * HTTPX と `pytest` に基づく極めて簡単なテスト @@ -452,24 +452,10 @@ item: Item ### アプリをデプロイ(任意) { #deploy-your-app-optional } -必要に応じて FastAPI アプリを FastAPI Cloud にデプロイできます。まだの場合はウェイティングリストに参加してください。 🚀 +必要に応じて FastAPI アプリを [FastAPI Cloud](https://fastapicloud.com) にデプロイできます。まだの場合はウェイティングリストに参加してください。 🚀 すでに **FastAPI Cloud** アカウント(ウェイティングリストから招待されました 😉)がある場合は、1 コマンドでアプリケーションをデプロイできます。 -デプロイ前に、ログインしていることを確認してください。 - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -次に、アプリをデプロイします。 -
```console @@ -488,7 +474,7 @@ Deploying to FastAPI Cloud... #### FastAPI Cloud について { #about-fastapi-cloud } -**FastAPI Cloud** は **FastAPI** の作者と同じチームによって作られています。 +**[FastAPI Cloud](https://fastapicloud.com)** は **FastAPI** の作者と同じチームによって作られています。 最小限の労力で API を **構築**、**デプロイ**、**アクセス** するためのプロセスを効率化します。 @@ -504,9 +490,9 @@ FastAPI はオープンソースであり、標準に基づいています。選 ## パフォーマンス { #performance } -独立した TechEmpower のベンチマークでは、Uvicorn で動作する **FastAPI** アプリケーションが、利用可能な最も高速な Python フレームワークの一つであり、Starlette と Uvicorn(FastAPI で内部的に使用されています)にのみ下回っていると示されています。(*) +独立した TechEmpower のベンチマークでは、Uvicorn で動作する **FastAPI** アプリケーションが、[利用可能な最も高速な Python フレームワークの一つ](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7)であり、Starlette と Uvicorn(FastAPI で内部的に使用されています)にのみ下回っていると示されています。(*) -詳細は Benchmarks セクションをご覧ください。 +詳細は [Benchmarks](https://fastapi.tiangolo.com/ja/benchmarks/) セクションをご覧ください。 ## 依存関係 { #dependencies } @@ -518,19 +504,19 @@ FastAPI を `pip install "fastapi[standard]"` でインストールすると、` Pydantic によって使用されるもの: -* email-validator - メール検証のため。 +* [`email-validator`](https://github.com/JoshData/python-email-validator) - メール検証のため。 Starlette によって使用されるもの: -* httpx - `TestClient` を使用したい場合に必要です。 -* jinja2 - デフォルトのテンプレート設定を使用したい場合に必要です。 -* python-multipart - `request.form()` とともに、フォームの 「parsing」 をサポートしたい場合に必要です。 +* [`httpx`](https://www.python-httpx.org) - `TestClient` を使用したい場合に必要です。 +* [`jinja2`](https://jinja.palletsprojects.com) - デフォルトのテンプレート設定を使用したい場合に必要です。 +* [`python-multipart`](https://github.com/Kludex/python-multipart) - `request.form()` とともに、フォームの 「parsing」 をサポートしたい場合に必要です。 FastAPI によって使用されるもの: -* uvicorn - アプリケーションをロードして提供するサーバーのため。これには `uvicorn[standard]` も含まれ、高性能なサービングに必要な依存関係(例: `uvloop`)が含まれます。 +* [`uvicorn`](https://www.uvicorn.dev) - アプリケーションをロードして提供するサーバーのため。これには `uvicorn[standard]` も含まれ、高性能なサービングに必要な依存関係(例: `uvloop`)が含まれます。 * `fastapi-cli[standard]` - `fastapi` コマンドを提供します。 - * これには `fastapi-cloud-cli` が含まれ、FastAPI アプリケーションを FastAPI Cloud にデプロイできます。 + * これには `fastapi-cloud-cli` が含まれ、FastAPI アプリケーションを [FastAPI Cloud](https://fastapicloud.com) にデプロイできます。 ### `standard` 依存関係なし { #without-standard-dependencies } @@ -546,13 +532,13 @@ FastAPI によって使用されるもの: 追加のオプション Pydantic 依存関係: -* pydantic-settings - 設定管理のため。 -* pydantic-extra-types - Pydantic で使用する追加の型のため。 +* [`pydantic-settings`](https://docs.pydantic.dev/latest/usage/pydantic_settings/) - 設定管理のため。 +* [`pydantic-extra-types`](https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/) - Pydantic で使用する追加の型のため。 追加のオプション FastAPI 依存関係: -* orjson - `ORJSONResponse` を使用したい場合に必要です。 -* ujson - `UJSONResponse` を使用したい場合に必要です。 +* [`orjson`](https://github.com/ijl/orjson) - `ORJSONResponse` を使用したい場合に必要です。 +* [`ujson`](https://github.com/esnme/ultrajson) - `UJSONResponse` を使用したい場合に必要です。 ## ライセンス { #license } diff --git a/docs/ja/docs/project-generation.md b/docs/ja/docs/project-generation.md index c930fb557c..b6550e3ac3 100644 --- a/docs/ja/docs/project-generation.md +++ b/docs/ja/docs/project-generation.md @@ -4,7 +4,7 @@ このテンプレートを使って開始できます。初期セットアップ、セキュリティ、データベース、いくつかのAPIエンドポイントがすでに用意されています。 -GitHubリポジトリ: Full Stack FastAPI Template +GitHubリポジトリ: [Full Stack FastAPI Template](https://github.com/tiangolo/full-stack-fastapi-template) ## Full Stack FastAPI テンプレート - 技術スタックと機能 { #full-stack-fastapi-template-technology-stack-and-features } diff --git a/docs/ja/docs/python-types.md b/docs/ja/docs/python-types.md index a6b46c256d..67336c31ef 100644 --- a/docs/ja/docs/python-types.md +++ b/docs/ja/docs/python-types.md @@ -231,7 +231,7 @@ def some_function(data: Any): {!> ../../docs_src/python_types/tutorial008b_py310.py!} ``` -これは `item` が `int` または `str` になり得ることを意味します. +これは `item` が `int` または `str` になり得ることを意味します。 #### `None` の可能性 { #possibly-none } @@ -269,7 +269,7 @@ def some_function(data: Any): ## Pydantic のモデル { #pydantic-models } -Pydantic はデータ検証を行うための Python ライブラリです。 +[Pydantic](https://docs.pydantic.dev/) はデータ検証を行うための Python ライブラリです。 データの「形」を属性付きのクラスとして宣言します。 @@ -285,13 +285,13 @@ Pydantic の公式ドキュメントからの例: /// info | 情報 -Pydantic の詳細はドキュメントを参照してください。 +[ Pydantic の詳細はドキュメントを参照してください](https://docs.pydantic.dev/)。 /// **FastAPI** はすべて Pydantic をベースにしています。 -すべてのことは [チュートリアル - ユーザーガイド](tutorial/index.md){.internal-link target=_blank} で実際に見ることができます。 +すべてのことは [チュートリアル - ユーザーガイド](tutorial/index.md) で実際に見ることができます。 ## メタデータアノテーション付き型ヒント { #type-hints-with-metadata-annotations } @@ -337,12 +337,12 @@ Python 自体は、この `Annotated` で何かをするわけではありませ * OpenAPI を使用して API を **ドキュメント化** します: * これは自動の対話型ドキュメントのユーザーインターフェイスで使われます。 -すべてが抽象的に聞こえるかもしれません。心配しないでください。 この全ての動作は [チュートリアル - ユーザーガイド](tutorial/index.md){.internal-link target=_blank} で見ることができます。 +すべてが抽象的に聞こえるかもしれません。心配しないでください。 この全ての動作は [チュートリアル - ユーザーガイド](tutorial/index.md) で見ることができます。 重要なのは、Python の標準的な型を使うことで、(クラスやデコレータなどを追加するのではなく)1 つの場所で **FastAPI** が多くの作業を代わりにやってくれているということです。 /// info | 情報 -すでにすべてのチュートリアルを終えて、型についての詳細を見るためにこのページに戻ってきた場合は、良いリソースとして `mypy` の「チートシート」 があります。 +すでにすべてのチュートリアルを終えて、型についての詳細を見るためにこのページに戻ってきた場合は、良いリソースとして [`mypy` の「チートシート`](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html) があります。 /// diff --git a/docs/ja/docs/tutorial/background-tasks.md b/docs/ja/docs/tutorial/background-tasks.md index d32c141b5b..0bacbb3947 100644 --- a/docs/ja/docs/tutorial/background-tasks.md +++ b/docs/ja/docs/tutorial/background-tasks.md @@ -63,7 +63,7 @@ ## 技術的な詳細 { #technical-details } -`BackgroundTasks` クラスは、`starlette.background`から直接取得されます。 +`BackgroundTasks` クラスは、[`starlette.background`](https://www.starlette.dev/background/) から直接取得されます。 これは、FastAPI に直接インポート/インクルードされるため、`fastapi` からインポートできる上に、`starlette.background`から別の `BackgroundTask` (末尾に `s` がない) を誤ってインポートすることを回避できます。 @@ -71,11 +71,11 @@ それでも、FastAPI で `BackgroundTask` を単独で使用することは可能ですが、コード内でオブジェクトを作成し、それを含むStarlette `Response` を返す必要があります。 -詳細については、Starlette のバックグラウンドタスクに関する公式ドキュメントを参照して下さい。 +詳細については、[Starlette のバックグラウンドタスクに関する公式ドキュメント](https://www.starlette.dev/background/)を参照して下さい。 ## 注意 { #caveat } -大量のバックグラウンド計算が必要であり、必ずしも同じプロセスで実行する必要がない場合 (たとえば、メモリや変数などを共有する必要がない場合)、Celery のようなより大きな他のツールを使用するとメリットがあるかもしれません。 +大量のバックグラウンド計算が必要であり、必ずしも同じプロセスで実行する必要がない場合 (たとえば、メモリや変数などを共有する必要がない場合)、[Celery](https://docs.celeryq.dev) のようなより大きな他のツールを使用するとメリットがあるかもしれません。 これらは、より複雑な構成、RabbitMQ や Redis などのメッセージ/ジョブキューマネージャーを必要とする傾向がありますが、複数のプロセス、特に複数のサーバーでバックグラウンドタスクを実行できます。 diff --git a/docs/ja/docs/tutorial/bigger-applications.md b/docs/ja/docs/tutorial/bigger-applications.md index 9c1cc0fe69..3518eaed39 100644 --- a/docs/ja/docs/tutorial/bigger-applications.md +++ b/docs/ja/docs/tutorial/bigger-applications.md @@ -58,17 +58,17 @@ from app.routers import items ```bash . -├── app # "app" is a Python package -│   ├── __init__.py # this file makes "app" a "Python package" -│   ├── main.py # "main" module, e.g. import app.main -│   ├── dependencies.py # "dependencies" module, e.g. import app.dependencies -│   └── routers # "routers" is a "Python subpackage" -│   │ ├── __init__.py # makes "routers" a "Python subpackage" -│   │ ├── items.py # "items" submodule, e.g. import app.routers.items -│   │ └── users.py # "users" submodule, e.g. import app.routers.users -│   └── internal # "internal" is a "Python subpackage" -│   ├── __init__.py # makes "internal" a "Python subpackage" -│   └── admin.py # "admin" submodule, e.g. import app.internal.admin +├── app # "app" は Python パッケージ +│   ├── __init__.py # このファイルにより "app" は「Python パッケージ」になる +│   ├── main.py # "main" モジュール(例: import app.main) +│   ├── dependencies.py # "dependencies" モジュール(例: import app.dependencies) +│   └── routers # "routers" は「Python サブパッケージ」 +│   │ ├── __init__.py # このファイルにより "routers" は「Python サブパッケージ」になる +│   │ ├── items.py # "items" サブモジュール(例: import app.routers.items) +│   │ └── users.py # "users" サブモジュール(例: import app.routers.users) +│   └── internal # "internal" は「Python サブパッケージ」 +│   ├── __init__.py # このファイルにより "internal" は「Python サブパッケージ」になる +│   └── admin.py # "admin" サブモジュール(例: import app.internal.admin) ``` ## `APIRouter` { #apirouter } @@ -123,7 +123,7 @@ from app.routers import items この例を簡単にするために架空のヘッダーを使っています。 -しかし実際には、組み込みの [Security utilities](security/index.md){.internal-link target=_blank} を使う方が良い結果になります。 +しかし実際には、組み込みの [Security utilities](security/index.md) を使う方が良い結果になります。 /// @@ -169,7 +169,7 @@ async def read_item(item_id: str): /// tip | 豆知識 -[*path operation デコレータ*の依存関係](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} と同様に、*path operation 関数*には値は渡されない点に注意してください。 +[*path operation デコレータ*の依存関係](dependencies/dependencies-in-path-operation-decorators.md) と同様に、*path operation 関数*には値は渡されない点に注意してください。 /// @@ -185,8 +185,8 @@ async def read_item(item_id: str): * すべてに事前定義した `responses` が含まれます。 * これらすべての *path operations* では、実行前に `dependencies` のリストが評価・実行されます。 * 特定の *path operation* に依存関係を宣言した場合は、**それらも実行されます**。 - * ルーターの依存関係が先に実行され、その後に[デコレータ内の `dependencies`](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}、次に通常のパラメータ依存関係が続きます。 - * [`scopes` を伴う `Security` 依存関係](../advanced/security/oauth2-scopes.md){.internal-link target=_blank} を追加することもできます。 + * ルーターの依存関係が先に実行され、その後に[デコレータ内の `dependencies`](dependencies/dependencies-in-path-operation-decorators.md)、次に通常のパラメータ依存関係が続きます。 + * [`scopes` を伴う `Security` 依存関係](../advanced/security/oauth2-scopes.md) を追加することもできます。 /// tip | 豆知識 @@ -303,7 +303,7 @@ from ...dependencies import get_token_header 通常どおり `FastAPI` クラスをインポートして作成します。 -さらに、各 `APIRouter` の依存関係と組み合わされる[グローバル依存関係](dependencies/global-dependencies.md){.internal-link target=_blank}も宣言できます: +さらに、各 `APIRouter` の依存関係と組み合わされる[グローバル依存関係](dependencies/global-dependencies.md)も宣言できます: {* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} @@ -353,7 +353,7 @@ from .routers import items, users from app.routers import items, users ``` -Python のパッケージとモジュールについて詳しくは、公式の Python モジュールに関するドキュメントをご覧ください。 +Python のパッケージとモジュールについて詳しくは、[公式の Python モジュールに関するドキュメント](https://docs.python.org/3/tutorial/modules.html)をご覧ください。 /// @@ -465,6 +465,37 @@ from .routers.users import router /// +## `pyproject.toml` の `entrypoint` を設定 { #configure-the-entrypoint-in-pyproject-toml } + +FastAPI の `app` オブジェクトは `app/main.py` にあるので、`pyproject.toml` で `entrypoint` を次のように設定できます: + +```toml +[tool.fastapi] +entrypoint = "app.main:app" +``` + +これは次のようにインポートするのと同等です: + +```python +from app.main import app +``` + +このようにすると、`fastapi` コマンドがアプリの場所を把握できます。 + +/// Note | 備考 + +コマンドにパスを渡すこともできます。例えば: + +```console +$ fastapi dev app/main.py +``` + +しかし、そのたびに `fastapi` コマンドを呼ぶ際、正しいパスを渡すのを忘れないようにする必要があります。 + +さらに、[VS Code Extension](../editor-support.md) や [FastAPI Cloud](https://fastapicloud.com) など、他のツールが見つけられない場合があります。そのため、`pyproject.toml` の `entrypoint` を使うことを推奨します。 + +/// + ## 自動APIドキュメントの確認 { #check-the-automatic-api-docs } アプリを実行します: @@ -472,14 +503,14 @@ from .routers.users import router
```console -$ fastapi dev app/main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-そして http://127.0.0.1:8000/docs を開きます。 +そして [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) を開きます。 すべてのサブモジュール由来のパスを含む自動 API ドキュメントが表示され、正しいパス(および prefix)と正しいタグが使われているのが分かります: diff --git a/docs/ja/docs/tutorial/body-nested-models.md b/docs/ja/docs/tutorial/body-nested-models.md index ab78b8f86a..5187eb14e5 100644 --- a/docs/ja/docs/tutorial/body-nested-models.md +++ b/docs/ja/docs/tutorial/body-nested-models.md @@ -96,7 +96,7 @@ Pydanticモデルの各属性には型があります。 `str`や`int`、`float`などの通常の単数型の他にも、`str`を継承したより複雑な単数型を使うこともできます。 -すべてのオプションをみるには、Pydanticの型の概要を確認してください。次の章でいくつかの例をみることができます。 +すべてのオプションをみるには、[Pydantic の型の概要](https://docs.pydantic.dev/latest/concepts/types/)を確認してください。次の章でいくつかの例をみることができます。 例えば、`Image`モデルのように`url`フィールドがある場合、`str`の代わりにPydanticの`HttpUrl`のインスタンスとして宣言することができます: diff --git a/docs/ja/docs/tutorial/body-updates.md b/docs/ja/docs/tutorial/body-updates.md index 310530c690..a4fa8bd7be 100644 --- a/docs/ja/docs/tutorial/body-updates.md +++ b/docs/ja/docs/tutorial/body-updates.md @@ -2,7 +2,7 @@ ## `PUT`による置換での更新 { #update-replacing-with-put } -項目を更新するにはHTTPの`PUT`操作を使用することができます。 +項目を更新するには[HTTPの`PUT`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT)操作を使用することができます。 `jsonable_encoder`を用いて、入力データをJSONとして保存できるデータに変換することができます(例:NoSQLデータベース)。例えば、`datetime`を`str`に変換します。 @@ -28,7 +28,7 @@ ## `PATCH`による部分的な更新 { #partial-updates-with-patch } -また、HTTPの`PATCH`操作でデータを*部分的に*更新することもできます。 +また、[HTTPの`PATCH`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH)操作でデータを*部分的に*更新することもできます。 つまり、更新したいデータだけを送信して、残りはそのままにしておくことができます。 @@ -68,7 +68,7 @@ まとめると、部分的な更新を適用するには、次のようにします: -* (オプションで)`PATCH`の代わりに`PUT`を使用します。 +* (オプションで)`PUT`の代わりに`PATCH`を使用します。 * 保存されているデータを取得します。 * そのデータをPydanticモデルにいれます。 * 入力モデルからデフォルト値を含まない`dict`を生成します(`exclude_unset`を使用します)。 @@ -95,6 +95,6 @@ そのため、すべての属性を省略できる部分的な変更を受け取りたい場合は、すべての属性をオプションとしてマークしたモデルを用意する必要があります(デフォルト値または`None`を使用して)。 -**更新** のためのオプション値がすべて設定されているモデルと、**作成** のための必須値が設定されているモデルを区別するには、[追加モデル](extra-models.md){.internal-link target=_blank}で説明されている考え方を利用することができます。 +**更新** のためのオプション値がすべて設定されているモデルと、**作成** のための必須値が設定されているモデルを区別するには、[追加モデル](extra-models.md)で説明されている考え方を利用することができます。 /// diff --git a/docs/ja/docs/tutorial/body.md b/docs/ja/docs/tutorial/body.md index 7c939bdfa0..9f100738c0 100644 --- a/docs/ja/docs/tutorial/body.md +++ b/docs/ja/docs/tutorial/body.md @@ -6,7 +6,7 @@ APIはほとんどの場合 **レスポンス** ボディを送信する必要があります。しかしクライアントは、常に **リクエストボディ** を送信する必要があるとは限りません。場合によっては、クエリパラメータ付きのパスだけをリクエストして、ボディを送信しないこともあります。 -**リクエスト**ボディを宣言するには、Pydantic モデルを使用し、その強力な機能とメリットをすべて利用します。 +**リクエスト**ボディを宣言するには、[Pydantic](https://docs.pydantic.dev/) モデルを使用し、その強力な機能とメリットをすべて利用します。 /// info | 情報 @@ -73,7 +73,7 @@ APIはほとんどの場合 **レスポンス** ボディを送信する必要 * データが無効な場合は、どこで何が不正なデータだったのかを正確に示す、分かりやすい明確なエラーを返します。 * 受け取ったデータをパラメータ `item` に渡します。 * 関数内で `Item` 型として宣言したため、すべての属性とその型について、エディタサポート(補完など)も利用できます。 -* モデル向けの JSON Schema 定義を生成します。プロジェクトにとって意味があるなら、他の場所でも好きなように利用できます。 +* モデル向けの [JSON Schema](https://json-schema.org) 定義を生成します。プロジェクトにとって意味があるなら、他の場所でも好きなように利用できます。 * それらのスキーマは生成されるOpenAPIスキーマの一部となり、自動ドキュメントの UIs で使用されます。 ## 自動ドキュメント { #automatic-docs } @@ -102,15 +102,15 @@ APIはほとんどの場合 **レスポンス** ボディを送信する必要 これをサポートするために、Pydantic自体にもいくつかの変更が加えられました。 -前述のスクリーンショットは Visual Studio Code で撮影されたものです。 +前述のスクリーンショットは [Visual Studio Code](https://code.visualstudio.com) で撮影されたものです。 -ただし、PyCharm や、他のほとんどのPythonエディタでも同じエディタサポートを得られます: +ただし、[PyCharm](https://www.jetbrains.com/pycharm/) や、他のほとんどのPythonエディタでも同じエディタサポートを得られます: /// tip | 豆知識 -エディタとして PyCharm を使用している場合、Pydantic PyCharm Plugin を使用できます。 +エディタとして [PyCharm](https://www.jetbrains.com/pycharm/) を使用している場合、[Pydantic PyCharm Plugin](https://github.com/koxudaxi/pydantic-pycharm-plugin/) を使用できます。 以下により、Pydanticモデルに対するエディタサポートが改善されます: @@ -163,4 +163,4 @@ FastAPIは、デフォルト値 `= None` があるため、`q` の値が必須 ## Pydanticを使わない方法 { #without-pydantic } -Pydanticモデルを使いたくない場合は、**Body** パラメータも使用できます。[Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank} のドキュメントを参照してください。 +Pydanticモデルを使いたくない場合は、**Body** パラメータも使用できます。[Body - 複数のパラメータ: ボディ内の単一値](body-multiple-params.md#singular-values-in-body) のドキュメントを参照してください。 diff --git a/docs/ja/docs/tutorial/cors.md b/docs/ja/docs/tutorial/cors.md index 5136a7fd5f..3716b179b9 100644 --- a/docs/ja/docs/tutorial/cors.md +++ b/docs/ja/docs/tutorial/cors.md @@ -1,6 +1,6 @@ # CORS (Cross-Origin Resource Sharing) { #cors-cross-origin-resource-sharing } -CORSまたは「Cross-Origin Resource Sharing」 は、ブラウザで実行されているフロントエンドにバックエンドと通信するJavaScriptコードがあり、そのバックエンドがフロントエンドとは異なる「オリジン」にある状況を指します。 +[CORSまたは「Cross-Origin Resource Sharing」](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) は、ブラウザで実行されているフロントエンドにバックエンドと通信するJavaScriptコードがあり、そのバックエンドがフロントエンドとは異なる「オリジン」にある状況を指します。 ## オリジン { #origin } @@ -56,10 +56,10 @@ * `allow_origins` - オリジン間リクエストを許可するオリジンのリスト。例えば、`['https://example.org', 'https://www.example.org']`。`['*']`を使用して任意のオリジンを許可できます。 * `allow_origin_regex` - オリジン間リクエストを許可するオリジンの正規表現文字列。例えば、`'https://.*\.example\.org'`。 * `allow_methods` - オリジン間リクエストで許可するHTTPメソッドのリスト。デフォルトは `['GET']` です。`['*']`を使用してすべての標準メソッドを許可できます。 -* `allow_headers` - オリジン間リクエストでサポートするHTTPリクエストヘッダーのリスト。デフォルトは `[]` です。`['*']`を使用して、すべてのヘッダーを許可できます。シンプルなCORSリクエストでは、 `Accept` 、 `Accept-Language` 、 `Content-Language` 、 `Content-Type` ヘッダーが常に許可されます。 +* `allow_headers` - オリジン間リクエストでサポートするHTTPリクエストヘッダーのリスト。デフォルトは `[]` です。`['*']`を使用して、すべてのヘッダーを許可できます。[シンプルなCORSリクエスト](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests)では、 `Accept` 、 `Accept-Language` 、 `Content-Language` 、 `Content-Type` ヘッダーが常に許可されます。 * `allow_credentials` - オリジン間リクエストでCookieをサポートする必要があることを示します。デフォルトは `False` です。 - `allow_credentials` が `True` に設定されている場合、`allow_origins`、`allow_methods`、`allow_headers` のいずれも `['*']` に設定できません。これらはすべて明示的に指定する必要があります。 + `allow_credentials` が `True` に設定されている場合、`allow_origins`、`allow_methods`、`allow_headers` のいずれも `['*']` に設定できません。これらはすべて[明示的に指定](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards)する必要があります。 * `expose_headers` - ブラウザからアクセスできるようにするレスポンスヘッダーを示します。デフォルトは `[]` です。 * `max_age` - ブラウザがCORSレスポンスをキャッシュする最大時間を秒単位で設定します。デフォルトは `600` です。 @@ -78,7 +78,7 @@ ## より詳しい情報 { #more-info } -CORSについてより詳しい情報は、Mozilla CORS documentation を参照して下さい。 +CORSについてより詳しい情報は、[Mozilla CORS documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) を参照して下さい。 /// note | 技術詳細 diff --git a/docs/ja/docs/tutorial/debugging.md b/docs/ja/docs/tutorial/debugging.md index 9d88ba42b5..023e988dce 100644 --- a/docs/ja/docs/tutorial/debugging.md +++ b/docs/ja/docs/tutorial/debugging.md @@ -59,7 +59,7 @@ Pythonによって自動的に作成されたファイル内の内部変数 `__n ```Python from myapp import app -# Some more code +# その他のコード ``` その場合、`myapp.py` 内の自動的に作成された変数 `__name__` は、値として `"__main__"` を持ちません。 @@ -74,7 +74,7 @@ from myapp import app /// info | 情報 -より詳しい情報は、公式Pythonドキュメントを参照してください。 +より詳しい情報は、[公式Pythonドキュメント](https://docs.python.org/3/library/__main__.html)を参照してください。 /// diff --git a/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index d0a2b16721..573ccc1f96 100644 --- a/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -32,7 +32,7 @@ この例では、架空のカスタムヘッダー `X-Key` と `X-Token` を使用しています。 -しかし実際のケースでセキュリティを実装する際は、統合された[Security utilities(次の章)](../security/index.md){.internal-link target=_blank}を使うことで、より多くの利点を得られます。 +しかし実際のケースでセキュリティを実装する際は、統合された[Security utilities(次の章)](../security/index.md)を使うことで、より多くの利点を得られます。 /// @@ -62,7 +62,7 @@ ## *path operation*のグループに対する依存関係 { #dependencies-for-a-group-of-path-operations } -後で、より大きなアプリケーションを(おそらく複数ファイルで)構造化する方法([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank})について読むときに、*path operation*のグループに対して単一の`dependencies`パラメータを宣言する方法を学びます。 +後で、より大きなアプリケーションを(おそらく複数ファイルで)構造化する方法([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md))について読むときに、*path operation*のグループに対して単一の`dependencies`パラメータを宣言する方法を学びます。 ## グローバル依存関係 { #global-dependencies } diff --git a/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md index 380dcb536b..83e4f88098 100644 --- a/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md @@ -14,8 +14,8 @@ FastAPIは、いくつかの`@contextlib.contextmanager`または -* `@contextlib.asynccontextmanager` +* [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) または +* [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) これらは **FastAPI** の依存関係として使用するのに有効です。 @@ -87,7 +87,7 @@ FastAPIは、いくつかのContext Managersのおかげで動作します。 +これはPythonの[コンテキストマネージャ](https://docs.python.org/3/library/contextlib.html)のおかげで動作します。 **FastAPI** はこれを実現するために内部的に使用しています。 @@ -111,7 +111,7 @@ FastAPIは、いくつかのファイルを読み込むには`with`を使用することができます: +例えば、[ファイルを読み込むには`with`を使用することができます](https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files): ```Python with open("./somefile.txt") as f: @@ -264,7 +264,7 @@ with open("./somefile.txt") as f: /// -Pythonでは、以下の2つのメソッドを持つクラスを作成する: `__enter__()`と`__exit__()`ことでコンテキストマネージャを作成することができます。 +Pythonでは、[以下の2つのメソッドを持つクラスを作成する: `__enter__()`と`__exit__()`](https://docs.python.org/3/reference/datamodel.html#context-managers)ことでコンテキストマネージャを作成することができます。 また、依存関数の中で`with`や`async with`文を使用することによって`yield`を持つ **FastAPI** の依存関係の中でそれらを使用することができます: @@ -272,10 +272,10 @@ Pythonでは、`@contextlib.contextmanager` または -* `@contextlib.asynccontextmanager` +* [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) または +* [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) これらを使って、関数を単一の`yield`でデコレートすることができます。 diff --git a/docs/ja/docs/tutorial/dependencies/global-dependencies.md b/docs/ja/docs/tutorial/dependencies/global-dependencies.md index 284da2181b..35a77a5f76 100644 --- a/docs/ja/docs/tutorial/dependencies/global-dependencies.md +++ b/docs/ja/docs/tutorial/dependencies/global-dependencies.md @@ -2,14 +2,14 @@ アプリケーションの種類によっては、アプリ全体に依存関係を追加したい場合があります。 -[`dependencies` を path operation のデコレータに追加](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}できるのと同様に、`FastAPI` アプリケーション自体にも追加できます。 +[`dependencies` を path operation のデコレータに追加](dependencies-in-path-operation-decorators.md)できるのと同様に、`FastAPI` アプリケーション自体にも追加できます。 その場合、アプリケーション内のすべての path operation に適用されます: {* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *} -また、[`dependencies` を path operation のデコレータに追加](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}する節で説明した考え方はすべて引き続き当てはまりますが、この場合はアプリ内のすべての path operation に対して適用されます。 +また、[`dependencies` を path operation のデコレータに追加](dependencies-in-path-operation-decorators.md)する節で説明した考え方はすべて引き続き当てはまりますが、この場合はアプリ内のすべての path operation に対して適用されます。 ## path operation のグループに対する依存関係 { #dependencies-for-groups-of-path-operations } -後で、複数ファイルを含む大規模アプリケーションの構成方法([大規模アプリケーション - 複数ファイル](../../tutorial/bigger-applications.md){.internal-link target=_blank})を読むと、path operation のグループに対して 1 つの `dependencies` パラメータを宣言する方法を学びます。 +後で、複数ファイルを含む大規模アプリケーションの構成方法([大規模アプリケーション - 複数ファイル](../../tutorial/bigger-applications.md))を読むと、path operation のグループに対して 1 つの `dependencies` パラメータを宣言する方法を学びます。 diff --git a/docs/ja/docs/tutorial/dependencies/index.md b/docs/ja/docs/tutorial/dependencies/index.md index 64cb4f79e4..a3cf3e26b5 100644 --- a/docs/ja/docs/tutorial/dependencies/index.md +++ b/docs/ja/docs/tutorial/dependencies/index.md @@ -57,7 +57,7 @@ FastAPI はバージョン 0.95.0 で `Annotated` のサポートを追加し( 古いバージョンを使用している場合、`Annotated` を使おうとするとエラーになります。 -`Annotated` を使用する前に、少なくとも 0.95.1 まで [FastAPI のバージョンをアップグレード](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} してください。 +`Annotated` を使用する前に、少なくとも 0.95.1 まで [FastAPI のバージョンをアップグレード](../../deployment/versions.md#upgrading-the-fastapi-versions) してください。 /// @@ -152,7 +152,7 @@ commons: Annotated[dict, Depends(common_parameters)] /// note | 備考 -わからない場合は、ドキュメントの[Async: *"In a hurry?"*](../../async.md#in-a-hurry){.internal-link target=_blank}の中の`async`と`await`についてのセクションを確認してください。 +わからない場合は、ドキュメントの[Async: *「急いでいますか?」*](../../async.md#in-a-hurry)の中の`async`と`await`についてのセクションを確認してください。 /// diff --git a/docs/ja/docs/tutorial/encoder.md b/docs/ja/docs/tutorial/encoder.md index 33cc6ae48c..e4745faf7c 100644 --- a/docs/ja/docs/tutorial/encoder.md +++ b/docs/ja/docs/tutorial/encoder.md @@ -12,7 +12,7 @@ JSON互換のデータのみを受信するデータベース`fake_db`がある 例えば、`datetime`オブジェクトはJSONと互換性がないので、受け取られません。 -そのため、`datetime`オブジェクトはISO形式のデータを含む`str`に変換されなければなりません。 +そのため、`datetime`オブジェクトは[ISO形式](https://en.wikipedia.org/wiki/ISO_8601)のデータを含む`str`に変換されなければなりません。 同様に、このデータベースはPydanticモデル(属性を持つオブジェクト)を受け取らず、`dict`だけを受け取ります。 @@ -24,7 +24,7 @@ Pydanticモデルのようなオブジェクトを受け取り、JSON互換版 この例では、Pydanticモデルを`dict`に、`datetime`を`str`に変換します。 -呼び出した結果は、Pythonの標準の`json.dumps()`でエンコードできるものです。 +呼び出した結果は、Pythonの標準の[`json.dumps()`](https://docs.python.org/3/library/json.html#json.dumps)でエンコードできるものです。 これはJSON形式のデータを含む大きな`str`を(文字列として)返しません。JSONと互換性のある値とサブの値を持つPython標準のデータ構造(例:`dict`)を返します。 diff --git a/docs/ja/docs/tutorial/extra-data-types.md b/docs/ja/docs/tutorial/extra-data-types.md index 4ed84e86f8..1bbfeb71e3 100644 --- a/docs/ja/docs/tutorial/extra-data-types.md +++ b/docs/ja/docs/tutorial/extra-data-types.md @@ -36,7 +36,7 @@ * `datetime.timedelta`: * Pythonの`datetime.timedelta`です。 * リクエストとレスポンスでは合計秒数の`float`で表現されます。 - * Pydanticでは「ISO 8601 time diff encoding」として表現することも可能です。詳細はドキュメントを参照してください。 + * Pydanticでは「ISO 8601 time diff encoding」として表現することも可能です。[詳細はドキュメントを参照してください](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers)。 * `frozenset`: * リクエストとレスポンスでは`set`と同じように扱われます: * リクエストでは、リストが読み込まれ、重複を排除して`set`に変換されます。 @@ -49,7 +49,7 @@ * `Decimal`: * Pythonの標準的な`Decimal`です。 * リクエストとレスポンスでは`float`と同じように扱われます。 -* Pydanticの全ての有効な型はこちらで確認できます: Pydantic data types。 +* 有効なPydanticのデータ型はここで確認できます: [Pydantic のデータ型](https://docs.pydantic.dev/latest/usage/types/types/)。 ## 例 { #example } diff --git a/docs/ja/docs/tutorial/extra-models.md b/docs/ja/docs/tutorial/extra-models.md index 951e8b35e4..20883068c2 100644 --- a/docs/ja/docs/tutorial/extra-models.md +++ b/docs/ja/docs/tutorial/extra-models.md @@ -12,7 +12,7 @@ ユーザーの平文のパスワードは絶対に保存しないでください。常に検証できる「安全なハッシュ」を保存してください。 -知らない方は、[セキュリティの章](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}で「パスワードハッシュ」とは何かを学ぶことができます。 +知らない方は、[セキュリティの章](security/simple-oauth2.md#password-hashing)で「パスワードハッシュ」とは何かを学ぶことができます。 /// @@ -162,11 +162,11 @@ UserInDB( OpenAPIでは`anyOf`で定義されます。 -そのためには、標準的なPythonの型ヒント`typing.Union`を使用します: +そのためには、標準的なPythonの型ヒント[`typing.Union`](https://docs.python.org/3/library/typing.html#typing.Union)を使用します: /// note | 備考 -`Union`を定義する場合は、最も具体的な型を先に、その後により具体性の低い型を含めてください。以下の例では、より具体的な`PlaneItem`が`Union[PlaneItem, CarItem]`内で`CarItem`より前に来ています。 +[`Union`](https://docs.pydantic.dev/latest/concepts/types/#unions)を定義する場合は、最も具体的な型を先に、その後により具体性の低い型を含めてください。以下の例では、より具体的な`PlaneItem`が`Union[PlaneItem, CarItem]`内で`CarItem`より前に来ています。 /// diff --git a/docs/ja/docs/tutorial/first-steps.md b/docs/ja/docs/tutorial/first-steps.md index 37d71a9f72..26cb49159c 100644 --- a/docs/ja/docs/tutorial/first-steps.md +++ b/docs/ja/docs/tutorial/first-steps.md @@ -11,7 +11,7 @@
```console -$ fastapi dev main.py +$ fastapi dev FastAPI Starting development server 🚀 @@ -58,7 +58,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ### チェック { #check-it } -ブラウザでhttp://127.0.0.1:8000を開きます。 +ブラウザで[http://127.0.0.1:8000](http://127.0.0.1:8000)を開きます。 次のようなJSONレスポンスが表示されます: @@ -68,17 +68,17 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ### 対話的APIドキュメント { #interactive-api-docs } -次に、http://127.0.0.1:8000/docsにアクセスします。 +次に、[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)にアクセスします。 -自動生成された対話的APIドキュメントが表示されます (Swagger UIで提供): +自動生成された対話的APIドキュメントが表示されます([Swagger UI](https://github.com/swagger-api/swagger-ui)で提供): ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) ### 代替APIドキュメント { #alternative-api-docs } -次に、http://127.0.0.1:8000/redocにアクセスします。 +次に、[http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)にアクセスします。 -先ほどとは異なる、自動生成された対話的APIドキュメントが表示されます (ReDocによって提供): +先ほどとは異なる、自動生成された対話的APIドキュメントが表示されます([ReDoc](https://github.com/Rebilly/ReDoc)によって提供): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -92,7 +92,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) #### API「スキーマ」 { #api-schema } -ここでは、OpenAPIはAPIのスキーマ定義の方法を規定する仕様です。 +ここでは、[OpenAPI](https://github.com/OAI/OpenAPI-Specification)はAPIのスキーマ定義の方法を規定する仕様です。 このスキーマ定義はAPIパス、受け取り可能なパラメータなどが含まれます。 @@ -110,7 +110,7 @@ OpenAPIはAPIのためのAPIスキーマを定義します。そして、その 素のOpenAPIスキーマがどのようなものか興味がある場合、FastAPIはすべてのAPIの説明を含むJSON(スキーマ)を自動的に生成します。 -次の場所で直接確認できます: http://127.0.0.1:8000/openapi.json. +次の場所で直接確認できます: [http://127.0.0.1:8000/openapi.json](http://127.0.0.1:8000/openapi.json). 次のようなJSONが表示されます。 @@ -143,9 +143,58 @@ OpenAPIスキーマは、FastAPIに含まれている2つのインタラクテ また、APIと通信するクライアント用のコードを自動的に生成するために使用することもできます。たとえば、フロントエンド、モバイル、またはIoTアプリケーションです。 +### `pyproject.toml`でアプリの`entrypoint`を設定 { #configure-the-app-entrypoint-in-pyproject-toml } + +`pyproject.toml`でアプリの場所を次のように設定できます: + +```toml +[tool.fastapi] +entrypoint = "main:app" +``` + +この`entrypoint`は、`fastapi`コマンドに対して、次のようにアプリをインポートすべきであることを伝えます: + +```python +from main import app +``` + +もしコード構成が次のようになっている場合: + +``` +. +├── backend +│   ├── main.py +│   ├── __init__.py +``` + +このときは`entrypoint`を次のように設定します: + +```toml +[tool.fastapi] +entrypoint = "backend.main:app" +``` + +これは次と同等です: + +```python +from backend.main import app +``` + +### パス付きの`fastapi dev` { #fastapi-dev-with-path } + +`fastapi dev`コマンドにファイルパスを渡すこともでき、使用すべきFastAPIのappオブジェクトを推測します: + +```console +$ fastapi dev main.py +``` + +ただし、その場合は毎回`fastapi`コマンドを呼ぶたびに正しいパスを渡すことを覚えておく必要があります。 + +さらに、他のツール(たとえば、[VS Code 拡張機能](../editor-support.md)や[FastAPI Cloud](https://fastapicloud.com))が見つけられない場合があります。そのため、`pyproject.toml`の`entrypoint`を使うことを推奨します。 + ### アプリをデプロイ(任意) { #deploy-your-app-optional } -任意でFastAPIアプリをFastAPI Cloudにデプロイできます。まだなら、待機リストに登録してください。 🚀 +任意でFastAPIアプリを[FastAPI Cloud](https://fastapicloud.com)にデプロイできます。まだなら、待機リストに登録してください。 🚀 すでに**FastAPI Cloud**アカウントがある場合(待機リストから招待済みの場合😉)、1コマンドでアプリケーションをデプロイできます。 @@ -191,7 +240,7 @@ Deploying to FastAPI Cloud... `FastAPI`は`Starlette`を直接継承するクラスです。 -`FastAPI`でもStarletteのすべての機能を利用可能です。 +`FastAPI`でも[Starlette](https://www.starlette.dev/)のすべての機能を利用可能です。 /// @@ -272,7 +321,7 @@ APIを構築するときは、通常、これらの特定のHTTPメソッドを * パス `/` * get オペレーション -/// info | `@decorator` Info +/// info | `@decorator` 情報 Pythonにおける`@something`シンタックスはデコレータと呼ばれます。 @@ -335,7 +384,7 @@ Pythonにおける`@something`シンタックスはデコレータと呼ばれ /// note | 備考 -違いが分からない場合は、[Async: *"急いでいますか?"*](../async.md#in-a-hurry){.internal-link target=_blank}を確認してください。 +違いが分からない場合は、[Async: *「急いでいますか?」*](../async.md#in-a-hurry)を確認してください。 /// @@ -351,11 +400,11 @@ JSONに自動的に変換されるオブジェクトやモデルは他にもた ### Step 6: デプロイする { #step-6-deploy-it } -**FastAPI Cloud**に1コマンドでアプリをデプロイします: `fastapi deploy`. 🎉 +**[FastAPI Cloud](https://fastapicloud.com)**に1コマンドでアプリをデプロイします: `fastapi deploy`. 🎉 #### FastAPI Cloudについて { #about-fastapi-cloud } -**FastAPI Cloud**は、**FastAPI**の作者とそのチームによって開発されています。 +**[FastAPI Cloud](https://fastapicloud.com)**は、**FastAPI**の作者とそのチームによって開発されています。 最小限の労力でAPIの**構築**、**デプロイ**、**アクセス**を行うプロセスを合理化します。 diff --git a/docs/ja/docs/tutorial/handling-errors.md b/docs/ja/docs/tutorial/handling-errors.md index dc74e3f6cc..8d0190cb0b 100644 --- a/docs/ja/docs/tutorial/handling-errors.md +++ b/docs/ja/docs/tutorial/handling-errors.md @@ -81,7 +81,7 @@ Pythonの例外なので、`return`ではなく、`raise`です。 ## カスタム例外ハンドラのインストール { #install-custom-exception-handlers } -カスタム例外ハンドラはStarletteと同じ例外ユーティリティを使用して追加することができます。 +カスタム例外ハンドラは[Starletteと同じ例外ユーティリティ](https://www.starlette.dev/exceptions/)を使用して追加することができます。 あなた(または使用しているライブラリ)が`raise`するかもしれないカスタム例外`UnicornException`があるとしましょう。 diff --git a/docs/ja/docs/tutorial/index.md b/docs/ja/docs/tutorial/index.md index d298abc62d..8182c92ae9 100644 --- a/docs/ja/docs/tutorial/index.md +++ b/docs/ja/docs/tutorial/index.md @@ -15,7 +15,7 @@
```console -$ fastapi dev main.py +$ fastapi dev FastAPI Starting development server 🚀 @@ -62,7 +62,7 @@ $ fastapi dev @@ -76,7 +76,7 @@ $ pip install "fastapi[standard]" /// note | 備考 -`pip install "fastapi[standard]"` でインストールすると、`fastapi-cloud-cli` を含むいくつかのデフォルトのオプション標準依存関係が付属します。これにより、FastAPI Cloud にデプロイできます。 +`pip install "fastapi[standard]"` でインストールすると、`fastapi-cloud-cli` を含むいくつかのデフォルトのオプション標準依存関係が付属します。これにより、[FastAPI Cloud](https://fastapicloud.com) にデプロイできます。 これらのオプション依存関係が不要な場合は、代わりに `pip install fastapi` をインストールできます。 @@ -84,6 +84,12 @@ $ pip install "fastapi[standard]" /// +/// tip | 豆知識 + +FastAPI には [VS Code の公式拡張機能](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode)(および Cursor)があります。path operation エクスプローラー、path operation 検索、テスト内の CodeLens ナビゲーション(テストから定義へジャンプ)、そして FastAPI Cloud へのデプロイやログなど、さまざまな機能をエディターから利用できます。 + +/// + ## 高度なユーザーガイド { #advanced-user-guide } この **チュートリアル - ユーザーガイド** の後で、後から読める **高度なユーザーガイド** もあります。 diff --git a/docs/ja/docs/tutorial/metadata.md b/docs/ja/docs/tutorial/metadata.md index 3b70bf2f41..6802e6c9aa 100644 --- a/docs/ja/docs/tutorial/metadata.md +++ b/docs/ja/docs/tutorial/metadata.md @@ -14,7 +14,7 @@ OpenAPI仕様および自動APIドキュメントUIで使用される次のフ | `version` | `string` | APIのバージョンです。これはOpenAPIのバージョンではなく、あなた自身のアプリケーションのバージョンです。たとえば `2.5.0` です。 | | `terms_of_service` | `str` | APIの利用規約へのURLです。指定する場合、URLである必要があります。 | | `contact` | `dict` | 公開されるAPIの連絡先情報です。複数のフィールドを含められます。
contact fields
ParameterTypeDescription
namestr連絡先の個人/組織を識別する名前です。
urlstr連絡先情報を指すURLです。URL形式である必要があります。
emailstr連絡先の個人/組織のメールアドレスです。メールアドレス形式である必要があります。
| -| `license_info` | `dict` | 公開されるAPIのライセンス情報です。複数のフィールドを含められます。
license_info fields
ParameterTypeDescription
namestr必須license_info が設定されている場合)。APIに使用されるライセンス名です。
identifierstrAPIの SPDX ライセンス式です。identifier フィールドは url フィールドと同時に指定できません。 OpenAPI 3.1.0、FastAPI 0.99.0 以降で利用できます。
urlstrAPIに使用されるライセンスへのURLです。URL形式である必要があります。
| +| `license_info` | `dict` | 公開されるAPIのライセンス情報です。複数のフィールドを含められます。
license_info fields
ParameterTypeDescription
namestr必須license_info が設定されている場合)。APIに使用されるライセンス名です。
identifierstrAPIの [SPDX](https://spdx.org/licenses/) ライセンス式です。identifier フィールドは url フィールドと同時に指定できません。 OpenAPI 3.1.0、FastAPI 0.99.0 以降で利用できます。
urlstrAPIに使用されるライセンスへのURLです。URL形式である必要があります。
| 以下のように設定できます: @@ -76,7 +76,7 @@ OpenAPI 3.1.0 および FastAPI 0.99.0 以降では、`license_info` を `url` /// info | 情報 -タグの詳細は [Path Operation Configuration](path-operation-configuration.md#tags){.internal-link target=_blank} を参照してください。 +タグの詳細は [Path Operation の設定](path-operation-configuration.md#tags) を参照してください。 /// diff --git a/docs/ja/docs/tutorial/middleware.md b/docs/ja/docs/tutorial/middleware.md index 103d6e2c06..20192d0805 100644 --- a/docs/ja/docs/tutorial/middleware.md +++ b/docs/ja/docs/tutorial/middleware.md @@ -15,7 +15,7 @@ `yield` を使った依存関係をもつ場合は、終了コードはミドルウェアの *後に* 実行されます。 -バックグラウンドタスク ([バックグラウンドタスク](background-tasks.md){.internal-link target=_blank} セクションで説明します。後で確認できます) がある場合は、それらは全てのミドルウェアの *後に* 実行されます。 +バックグラウンドタスク ([バックグラウンドタスク](background-tasks.md) セクションで説明します。後で確認できます) がある場合は、それらは全てのミドルウェアの *後に* 実行されます。 /// @@ -35,9 +35,9 @@ /// tip | 豆知識 -カスタムの独自ヘッダーは `X-` プレフィックスを使用して追加できる点に注意してください。 +カスタムの独自ヘッダーは [`X-` プレフィックスを使用](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)して追加できる点に注意してください。 -ただし、ブラウザのクライアントに表示させたいカスタムヘッダーがある場合は、StarletteのCORSドキュメントに記載されているパラメータ `expose_headers` を使用して、それらをCORS設定に追加する必要があります ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank})。 +ただし、ブラウザのクライアントに表示させたいカスタムヘッダーがある場合は、[CORS (Cross-Origin Resource Sharing)](cors.md) の設定に、[StarletteのCORSドキュメント](https://www.starlette.dev/middleware/#corsmiddleware)に記載されているパラメータ `expose_headers` を使用して、それらを追加する必要があります。 /// @@ -61,7 +61,7 @@ /// tip | 豆知識 -ここでは、これらのユースケースに対してより正確になり得るため、`time.time()` の代わりに `time.perf_counter()` を使用しています。 🤓 +ここでは、これらのユースケースに対してより正確になり得るため、`time.time()` の代わりに [`time.perf_counter()`](https://docs.python.org/3/library/time.html#time.perf_counter) を使用しています。 🤓 /// @@ -90,6 +90,6 @@ app.add_middleware(MiddlewareB) ## その他のミドルウェア { #other-middlewares } -他のミドルウェアの詳細については、[高度なユーザーガイド: 高度なミドルウェア](../advanced/middleware.md){.internal-link target=_blank}を参照してください。 +他のミドルウェアの詳細については、[高度なユーザーガイド: 高度なミドルウェア](../advanced/middleware.md)を参照してください。 次のセクションでは、ミドルウェアを使用して CORS を処理する方法について説明します。 diff --git a/docs/ja/docs/tutorial/path-operation-configuration.md b/docs/ja/docs/tutorial/path-operation-configuration.md index 556cc6b148..25a2783ea1 100644 --- a/docs/ja/docs/tutorial/path-operation-configuration.md +++ b/docs/ja/docs/tutorial/path-operation-configuration.md @@ -58,7 +58,7 @@ 説明文は長くて複数行におよぶ傾向があるので、関数docstring内に*path operation*の説明文を宣言できます。すると、**FastAPI** は説明文を読み込んでくれます。 -docstringにMarkdownを記述すれば、正しく解釈されて表示されます。(docstringのインデントを考慮して) +docstringに[Markdown](https://en.wikipedia.org/wiki/Markdown)を記述すれば、正しく解釈されて表示されます。(docstringのインデントを考慮して) {* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *} diff --git a/docs/ja/docs/tutorial/path-params-numeric-validations.md b/docs/ja/docs/tutorial/path-params-numeric-validations.md index ab3240f042..55930eece2 100644 --- a/docs/ja/docs/tutorial/path-params-numeric-validations.md +++ b/docs/ja/docs/tutorial/path-params-numeric-validations.md @@ -14,7 +14,7 @@ FastAPI はバージョン 0.95.0 で`Annotated`のサポートを追加し( 古いバージョンの場合、`Annotated`を使おうとするとエラーになります。 -`Annotated`を使用する前に、FastAPI のバージョンを少なくとも 0.95.1 まで[アップグレードしてください](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}。 +`Annotated`を使用する前に、FastAPI のバージョンを少なくとも 0.95.1 まで[アップグレードしてください](../deployment/versions.md#upgrading-the-fastapi-versions)。 /// @@ -122,7 +122,7 @@ Pythonはその`*`で何かをすることはありませんが、それ以降 ## まとめ { #recap } -`Query`と`Path`(そしてまだ見たことない他のもの)では、[クエリパラメータと文字列の検証](query-params-str-validations.md){.internal-link target=_blank}と同じようにメタデータと文字列の検証を宣言することができます。 +`Query`と`Path`(そしてまだ見たことない他のもの)では、[クエリパラメータと文字列の検証](query-params-str-validations.md)と同じようにメタデータと文字列の検証を宣言することができます。 また、数値のバリデーションを宣言することもできます: diff --git a/docs/ja/docs/tutorial/path-params.md b/docs/ja/docs/tutorial/path-params.md index 5b78eb7b1f..8556b1c375 100644 --- a/docs/ja/docs/tutorial/path-params.md +++ b/docs/ja/docs/tutorial/path-params.md @@ -6,7 +6,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー パスパラメータ `item_id` の値は、引数 `item_id` として関数に渡されます。 -したがって、この例を実行して http://127.0.0.1:8000/items/foo にアクセスすると、次のレスポンスが表示されます。 +したがって、この例を実行して [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/items/foo) にアクセスすると、次のレスポンスが表示されます。 ```JSON {"item_id":"foo"} @@ -28,7 +28,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー ## データ変換 { #data-conversion } -この例を実行し、ブラウザで http://127.0.0.1:8000/items/3 を開くと、次のレスポンスが表示されます: +この例を実行し、ブラウザで [http://127.0.0.1:8000/items/3](http://127.0.0.1:8000/items/3) を開くと、次のレスポンスが表示されます: ```JSON {"item_id":3} @@ -44,7 +44,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー ## データバリデーション { #data-validation } -しかしブラウザで http://127.0.0.1:8000/items/foo を開くと、次のHTTPエラーが表示されます: +しかしブラウザで [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/items/foo) を開くと、次のHTTPエラーが表示されます: ```JSON { @@ -64,7 +64,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー これは、パスパラメータ `item_id` が `int` ではない値 `"foo"` だからです。 -http://127.0.0.1:8000/items/4.2 で見られるように、`int` のかわりに `float` が与えられた場合にも同様なエラーが表示されます。 +[http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) で見られるように、`int` のかわりに `float` が与えられた場合にも同様なエラーが表示されます。 /// check | 確認 @@ -78,7 +78,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー ## ドキュメント { #documentation } -そしてブラウザで http://127.0.0.1:8000/docs を開くと、以下の様な自動的に生成された対話的なAPIドキュメントが表示されます。 +そしてブラウザで [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) を開くと、以下の様な自動的に生成された対話的なAPIドキュメントが表示されます。 @@ -92,9 +92,9 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー ## 標準ベースのメリット、ドキュメンテーションの代替物 { #standards-based-benefits-alternative-documentation } -また、生成されたスキーマが OpenAPI 標準に従っているので、互換性のあるツールが多数あります。 +また、生成されたスキーマが [OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md) 標準に従っているので、互換性のあるツールが多数あります。 -このため、**FastAPI**自体が代替のAPIドキュメントを提供します(ReDocを使用)。これは、 http://127.0.0.1:8000/redoc にアクセスすると確認できます。 +このため、**FastAPI**自体が代替のAPIドキュメントを提供します(ReDocを使用)。これは、 [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) にアクセスすると確認できます。 @@ -102,7 +102,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー ## Pydantic { #pydantic } -すべてのデータバリデーションは Pydantic によって内部で実行されるため、Pydanticの全てのメリットが得られます。そして、安心して利用することができます。 +すべてのデータバリデーションは [Pydantic](https://docs.pydantic.dev/) によって内部で実行されるため、Pydanticの全てのメリットが得られます。そして、安心して利用することができます。 `str`、 `float` 、 `bool` および他の多くの複雑なデータ型を型宣言に使用できます。 diff --git a/docs/ja/docs/tutorial/query-params-str-validations.md b/docs/ja/docs/tutorial/query-params-str-validations.md index dda4e120bf..d340598019 100644 --- a/docs/ja/docs/tutorial/query-params-str-validations.md +++ b/docs/ja/docs/tutorial/query-params-str-validations.md @@ -35,13 +35,13 @@ FastAPI はバージョン 0.95.0 で `Annotated` のサポートを追加し( 古いバージョンの場合、`Annotated` を使おうとするとエラーになります。 -`Annotated` を使う前に、FastAPI のバージョンを少なくとも 0.95.1 にするために、[FastAPI のバージョンをアップグレード](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}してください。 +`Annotated` を使う前に、FastAPI のバージョンを少なくとも 0.95.1 にするために、[FastAPI のバージョンをアップグレード](../deployment/versions.md#upgrading-the-fastapi-versions)してください。 /// ## `q` パラメータの型で `Annotated` を使う { #use-annotated-in-the-type-for-the-q-parameter } -以前、[Python Types Intro](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank} で `Annotated` を使ってパラメータにメタデータを追加できると説明したことを覚えていますか? +以前、[Python Types Intro](../python-types.md#type-hints-with-metadata-annotations) で `Annotated` を使ってパラメータにメタデータを追加できると説明したことを覚えていますか? いよいよ FastAPI で使うときです。 🚀 @@ -158,7 +158,7 @@ FastAPI なしで同じ関数を **別の場所** から **呼び出しても** `Annotated` を使わずに **(古い)デフォルト値スタイル** を使う場合、FastAPI なしでその関数を **別の場所** で呼び出すとき、正しく動かすために関数へ引数を渡すことを **覚えておく** 必要があります。そうしないと値が期待と異なります(例えば `str` の代わりに `QueryInfo` か、それに類するものになります)。また、エディターも警告せず、Python もその関数の実行で文句を言いません。内部の処理がエラーになるときに初めて問題が出ます。 -`Annotated` は複数のメタデータアノテーションを持てるので、Typer のような別ツールと同じ関数を使うこともできます。 🚀 +`Annotated` は複数のメタデータアノテーションを持てるので、[Typer](https://typer.tiangolo.com/) のような別ツールと同じ関数を使うこともできます。 🚀 ## バリデーションをさらに追加する { #add-more-validations } @@ -348,7 +348,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems さて、このパラメータが気に入らなくなったとしましょう。 -それを使っているクライアントがいるので、しばらくは残しておく必要がありますが、ドキュメントにはdeprecatedと明記しておきたいです。 +それを使っているクライアントがいるので、しばらくは残しておく必要がありますが、ドキュメントには廃止予定と明記しておきたいです。 その場合、`Query`にパラメータ`deprecated=True`を渡します: @@ -370,11 +370,11 @@ http://127.0.0.1:8000/items/?item-query=foobaritems その場合、通常のバリデーション(例: 値が `str` であることの検証)の後に適用される **カスタムバリデータ関数** を使えます。 -これを行うには、`Annotated` の中で Pydantic の `AfterValidator` を使います。 +これを行うには、`Annotated` の中で [Pydantic の `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) を使います。 /// tip | 豆知識 -Pydantic には `BeforeValidator` などもあります。 🤓 +Pydantic には [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-before-validator) などもあります。 🤓 /// diff --git a/docs/ja/docs/tutorial/query-params.md b/docs/ja/docs/tutorial/query-params.md index d32c9822b8..51e4eb944f 100644 --- a/docs/ja/docs/tutorial/query-params.md +++ b/docs/ja/docs/tutorial/query-params.md @@ -183,6 +183,6 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy /// tip | 豆知識 -[パスパラメータ](path-params.md#predefined-values){.internal-link target=_blank}と同様に `Enum` を使用できます。 +[パスパラメータ](path-params.md#predefined-values)と同様に `Enum` を使用できます。 /// diff --git a/docs/ja/docs/tutorial/request-files.md b/docs/ja/docs/tutorial/request-files.md index 538cf64744..30a494afb0 100644 --- a/docs/ja/docs/tutorial/request-files.md +++ b/docs/ja/docs/tutorial/request-files.md @@ -4,9 +4,9 @@ /// info | 情報 -アップロードされたファイルを受け取るには、まず `python-multipart` をインストールします。 +アップロードされたファイルを受け取るには、まず [`python-multipart`](https://github.com/Kludex/python-multipart) をインストールします。 -[仮想環境](../virtual-environments.md){.internal-link target=_blank}を作成して有効化し、次のようにインストールしてください: +[仮想環境](../virtual-environments.md)を作成して有効化し、次のようにインストールしてください: ```console $ pip install python-multipart @@ -63,8 +63,8 @@ $ pip install python-multipart - 最大サイズまではメモリに保持し、それを超えるとディスクに格納されるファイルです。 - そのため、画像・動画・大きなバイナリなどの大きなファイルでも、メモリを使い果たすことなくうまく動作します。 - アップロードされたファイルからメタデータを取得できます。 -- file-like な `async` インターフェースを持ちます。 -- 実際の Python の `SpooledTemporaryFile` オブジェクトを公開しており、file-like オブジェクトを期待する他のライブラリにそのまま渡せます。 +- [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) な `async` インターフェースを持ちます。 +- 実際の Python の [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) オブジェクトを公開しており、file-like オブジェクトを期待する他のライブラリにそのまま渡せます。 ### `UploadFile` { #uploadfile } @@ -72,7 +72,7 @@ $ pip install python-multipart - `filename`: アップロード時の元のファイル名を表す `str`(例: `myimage.jpg`) - `content_type`: コンテントタイプ(MIME タイプ / メディアタイプ)を表す `str`(例: `image/jpeg`) -- `file`: `SpooledTemporaryFile`file-like なオブジェクト)。これは実際の Python のファイルオブジェクトで、「file-like」オブジェクトを期待する関数やライブラリに直接渡せます。 +- `file`: [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile)([file-like](https://docs.python.org/3/glossary.html#term-file-like-object) なオブジェクト)。これは実際の Python のファイルオブジェクトで、「file-like」オブジェクトを期待する関数やライブラリに直接渡せます。 `UploadFile` には次の `async` メソッドがあります。いずれも内部で対応するファイルメソッド(内部の `SpooledTemporaryFile`)を呼び出します。 @@ -121,7 +121,7 @@ HTML フォーム(`
`)がサーバーにデータを送る方法 ただしフォームにファイルが含まれる場合は、`multipart/form-data` としてエンコードされます。`File` を使うと、**FastAPI** はボディ内の正しい部分からファイルを取得すべきであると認識します。 -これらのエンコーディングやフォームフィールドの詳細は、MDN Web Docs の POST を参照してください。 +これらのエンコーディングやフォームフィールドの詳細は、[MDN Web Docs の `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) を参照してください。 /// diff --git a/docs/ja/docs/tutorial/request-form-models.md b/docs/ja/docs/tutorial/request-form-models.md index 071867964b..62aa9e2985 100644 --- a/docs/ja/docs/tutorial/request-form-models.md +++ b/docs/ja/docs/tutorial/request-form-models.md @@ -1,12 +1,12 @@ # フォームモデル { #form-models } -FastAPI では、フォームフィールドを宣言するために Pydantic モデルを使用できます。 +FastAPI では、フォームフィールドを宣言するために **Pydantic モデル**を使用できます。 /// info | 情報 -フォームを使うには、まず `python-multipart` をインストールします。 +フォームを使うには、まず [`python-multipart`](https://github.com/Kludex/python-multipart) をインストールします。 -まず [仮想環境](../virtual-environments.md){.internal-link target=_blank} を作成して有効化し、そのうえでインストールしてください。例えば: +まず [仮想環境](../virtual-environments.md) を作成して有効化し、そのうえでインストールしてください。例えば: ```console $ pip install python-multipart diff --git a/docs/ja/docs/tutorial/request-forms-and-files.md b/docs/ja/docs/tutorial/request-forms-and-files.md index 9a4e299e91..651f07ff01 100644 --- a/docs/ja/docs/tutorial/request-forms-and-files.md +++ b/docs/ja/docs/tutorial/request-forms-and-files.md @@ -4,9 +4,9 @@ /// info | 情報 -アップロードされたファイルやフォームデータを受信するには、まず`python-multipart`をインストールします。 +アップロードされたファイルやフォームデータを受信するには、まず[`python-multipart`](https://github.com/Kludex/python-multipart)をインストールします。 -[仮想環境](../virtual-environments.md){.internal-link target=_blank}を作成し、それを有効化してから、例えば次のようにインストールしてください: +[仮想環境](../virtual-environments.md)を作成し、それを有効化してから、例えば次のようにインストールしてください: ```console $ pip install python-multipart diff --git a/docs/ja/docs/tutorial/request-forms.md b/docs/ja/docs/tutorial/request-forms.md index dda2a4bf7f..c6b2a921a6 100644 --- a/docs/ja/docs/tutorial/request-forms.md +++ b/docs/ja/docs/tutorial/request-forms.md @@ -4,9 +4,9 @@ JSONの代わりにフィールドを受け取る場合は、`Form`を使用し /// info | 情報 -フォームを使うためには、まず`python-multipart`をインストールします。 +フォームを使うためには、まず[`python-multipart`](https://github.com/Kludex/python-multipart)をインストールします。 -必ず[仮想環境](../virtual-environments.md){.internal-link target=_blank}を作成して有効化してから、例えば次のようにインストールしてください: +必ず[仮想環境](../virtual-environments.md)を作成して有効化してから、例えば次のようにインストールしてください: ```console $ pip install python-multipart @@ -56,7 +56,7 @@ HTMLフォーム(`
`)がサーバにデータを送信する方 しかし、フォームがファイルを含む場合は、`multipart/form-data`としてエンコードされます。ファイルの扱いについては次の章で説明します。 -これらのエンコーディングやフォームフィールドの詳細については、MDNPOSTのウェブドキュメントを参照してください。 +これらのエンコーディングやフォームフィールドの詳細については、[MDN の `POST` ウェブドキュメント](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)を参照してください。 /// diff --git a/docs/ja/docs/tutorial/response-model.md b/docs/ja/docs/tutorial/response-model.md index 07dc201233..b4024e0a02 100644 --- a/docs/ja/docs/tutorial/response-model.md +++ b/docs/ja/docs/tutorial/response-model.md @@ -13,6 +13,7 @@ FastAPIはこの戻り値の型を使って以下を行います: * OpenAPIの *path operation* に、レスポンス用の **JSON Schema** を追加します。 * これは**自動ドキュメント**で使用されます。 * 自動クライアントコード生成ツールでも使用されます。 +* 返却データを Pydantic を使ってJSONに**シリアライズ**します。Pydantic は内部が**Rust**で実装されているため、**非常に高速**です。 しかし、最も重要なのは: @@ -73,9 +74,9 @@ FastAPIはこの `response_model` を使って、データのドキュメント /// info | 情報 -`EmailStr` を使用するには、最初に `email-validator` をインストールしてください。 +`EmailStr` を使用するには、最初に [`email-validator`](https://github.com/JoshData/python-email-validator) をインストールしてください。 -[仮想環境](../virtual-environments.md){.internal-link target=_blank}を作成して有効化してから、例えば次のようにインストールしてください: +[仮想環境](../virtual-environments.md)を作成して有効化してから、例えば次のようにインストールしてください: ```console $ pip install email-validator @@ -181,7 +182,7 @@ Pydanticフィールドとして有効ではないものを返し、ツール( ### レスポンスを直接返す { #return-a-response-directly } -最も一般的なケースは、[高度なドキュメントで後述する「Responseを直接返す」](../advanced/response-directly.md){.internal-link target=_blank}場合です。 +最も一般的なケースは、[高度なドキュメントで後述する「Responseを直接返す」](../advanced/response-directly.md)場合です。 {* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} @@ -257,7 +258,7 @@ Pydanticフィールドとして有効ではないものを返し、ツール( * `response_model_exclude_defaults=True` * `response_model_exclude_none=True` -`exclude_defaults` と `exclude_none` については、Pydanticのドキュメントで説明されている通りです。 +`exclude_defaults` と `exclude_none` については、[Pydanticのドキュメント](https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict)で説明されている通りです。 /// diff --git a/docs/ja/docs/tutorial/response-status-code.md b/docs/ja/docs/tutorial/response-status-code.md index d4ac45da65..9237ac784d 100644 --- a/docs/ja/docs/tutorial/response-status-code.md +++ b/docs/ja/docs/tutorial/response-status-code.md @@ -20,7 +20,7 @@ /// info | 情報 -`status_code`は代わりに、Pythonの`http.HTTPStatus`のように、`IntEnum`を受け取ることもできます。 +`status_code`は代わりに、Pythonの[`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus)のように、`IntEnum`を受け取ることもできます。 /// @@ -66,7 +66,7 @@ HTTPでは、レスポンスの一部として3桁の数字のステータスコ /// tip | 豆知識 -それぞれのステータスコードとどのコードが何のためのコードなのかについて詳細はMDN documentation about HTTP status codesを参照してください。 +それぞれのステータスコードとどのコードが何のためのコードなのかについての詳細は、[MDN のHTTPステータスコードに関するドキュメント](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)を参照してください。 /// @@ -92,10 +92,10 @@ HTTPでは、レスポンスの一部として3桁の数字のステータスコ また、`from starlette import status`を使うこともできます。 -**FastAPI** は、`開発者の利便性を考慮して、fastapi.status`と同じ`starlette.status`を提供しています。しかし、これはStarletteから直接提供されています。 +**FastAPI** は、開発者の利便性を考慮して、fastapi.statusと同じ`starlette.status`を提供しています。しかし、これはStarletteから直接提供されています。 /// ## デフォルトの変更 { #changing-the-default } -後に、[高度なユーザーガイド](../advanced/response-change-status-code.md){.internal-link target=_blank}で、ここで宣言しているデフォルトとは異なるステータスコードを返す方法を見ていきます。 +後に、[高度なユーザーガイド](../advanced/response-change-status-code.md)で、ここで宣言しているデフォルトとは異なるステータスコードを返す方法を見ていきます。 diff --git a/docs/ja/docs/tutorial/schema-extra-example.md b/docs/ja/docs/tutorial/schema-extra-example.md index 76a6b0f949..87ee85f402 100644 --- a/docs/ja/docs/tutorial/schema-extra-example.md +++ b/docs/ja/docs/tutorial/schema-extra-example.md @@ -12,7 +12,7 @@ その追加情報は、そのモデルの出力**JSON Schema**にそのまま追加され、APIドキュメントで使用されます。 -Pydanticのドキュメント: Configurationで説明されているように、`dict`を受け取る属性`model_config`を使用できます。 +[Pydanticのドキュメント: Configuration](https://docs.pydantic.dev/latest/api/config/)で説明されているように、`dict`を受け取る属性`model_config`を使用できます。 生成されるJSON Schemaに表示したい追加データ(`examples`を含む)を含む`dict`を使って、`"json_schema_extra"`を設定できます。 @@ -145,12 +145,12 @@ JSON Schemaには`examples`がなかったため、OpenAPIは自身が改変し OpenAPIは、仕様の他の部分にも`example`と`examples`フィールドを追加しました: -* `Parameter Object`(仕様内)。FastAPIの以下で使用されました: +* [`Parameter Object`(仕様内)](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-object)。FastAPIの以下で使用されました: * `Path()` * `Query()` * `Header()` * `Cookie()` -* `Request Body Object`。仕様内の`Media Type Object`の`content`フィールド(仕様内)。FastAPIの以下で使用されました: +* [`Request Body Object`、`Media Type Object`の`content`フィールド(仕様内)](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#media-type-object)。FastAPIの以下で使用されました: * `Body()` * `File()` * `Form()` @@ -163,7 +163,7 @@ OpenAPIは、仕様の他の部分にも`example`と`examples`フィールドを ### JSON Schemaの`examples`フィールド { #json-schemas-examples-field } -しかしその後、JSON Schemaは新しいバージョンの仕様に`examples`フィールドを追加しました。 +しかしその後、JSON Schemaは新しいバージョンの仕様に[`examples`](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5)フィールドを追加しました。 そして、新しいOpenAPI 3.1.0は、この新しいフィールド`examples`を含む最新バージョン(JSON Schema 2020-12)に基づくようになりました。 diff --git a/docs/ja/docs/tutorial/security/first-steps.md b/docs/ja/docs/tutorial/security/first-steps.md index 5bf04386a8..e678ebce1c 100644 --- a/docs/ja/docs/tutorial/security/first-steps.md +++ b/docs/ja/docs/tutorial/security/first-steps.md @@ -26,11 +26,11 @@ /// info | 情報 -`python-multipart` パッケージは、`pip install "fastapi[standard]"` コマンドを実行すると **FastAPI** と一緒に自動的にインストールされます。 +[`python-multipart`](https://github.com/Kludex/python-multipart) パッケージは、`pip install "fastapi[standard]"` コマンドを実行すると **FastAPI** と一緒に自動的にインストールされます。 しかし、`pip install fastapi` コマンドを使用する場合、`python-multipart` パッケージはデフォルトでは含まれません。 -手動でインストールするには、[仮想環境](../../virtual-environments.md){.internal-link target=_blank}を作成して有効化し、次のコマンドでインストールしてください: +手動でインストールするには、[仮想環境](../../virtual-environments.md)を作成して有効化し、次のコマンドでインストールしてください: ```console $ pip install python-multipart @@ -45,7 +45,7 @@ $ pip install python-multipart
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -54,7 +54,7 @@ $ fastapi dev main.py ## 確認 { #check-it } -次のインタラクティブなドキュメントにアクセスしてください: http://127.0.0.1:8000/docs。 +次のインタラクティブなドキュメントにアクセスしてください: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 下記のように見えるでしょう: @@ -140,7 +140,7 @@ OAuth2は、バックエンドやAPIがユーザーを認証するサーバー 相対URLを使っているので、APIが`https://example.com/`にある場合、`https://example.com/token`を参照します。しかし、APIが`https://example.com/api/v1/`にある場合は`https://example.com/api/v1/token`を参照することになります。 -相対 URL を使うことは、[プロキシの背後](../../advanced/behind-a-proxy.md){.internal-link target=_blank}のような高度なユースケースでもアプリケーションを動作させ続けるために重要です。 +相対 URL を使うことは、[プロキシの背後](../../advanced/behind-a-proxy.md)のような高度なユースケースでもアプリケーションを動作させ続けるために重要です。 /// diff --git a/docs/ja/docs/tutorial/security/oauth2-jwt.md b/docs/ja/docs/tutorial/security/oauth2-jwt.md index 0d6be90a24..9c527121ea 100644 --- a/docs/ja/docs/tutorial/security/oauth2-jwt.md +++ b/docs/ja/docs/tutorial/security/oauth2-jwt.md @@ -24,13 +24,13 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4 1週間後、トークンが期限切れとなるとどうなるでしょうか?ユーザーは認可されず、新しいトークンを得るために再びサインインしなければなりません。また、ユーザー(または第三者)がトークンを修正して有効期限を変更しようとした場合、署名が一致しないため、トークンの修正を検知できます。 -JWT トークンを使って遊んでみたいという方は、https://jwt.io をチェックしてください。 +JWT トークンを使って遊んでみたいという方は、[https://jwt.io](https://jwt.io/) をチェックしてください。 ## `PyJWT` のインストール { #install-pyjwt } PythonでJWTトークンの生成と検証を行うために、`PyJWT`をインストールする必要があります。 -[仮想環境](../../virtual-environments.md){.internal-link target=_blank}を作成し、アクティベートしてから、`pyjwt`をインストールしてください。 +[仮想環境](../../virtual-environments.md)を作成し、アクティベートしてから、`pyjwt`をインストールしてください。
@@ -46,7 +46,7 @@ $ pip install pyjwt RSAやECDSAのようなデジタル署名アルゴリズムを使用する予定がある場合は、cryptographyライブラリの依存関係`pyjwt[crypto]`をインストールしてください。 -詳細はPyJWT Installation docsで確認できます。 +詳細は[PyJWT Installation docs](https://pyjwt.readthedocs.io/en/latest/installation.html)で確認できます。 /// @@ -72,7 +72,7 @@ pwdlib は、パスワードのハッシュを処理するための優れたPyth 推奨されるアルゴリズムは「Argon2」です。 -[仮想環境](../../virtual-environments.md){.internal-link target=_blank}を作成し、アクティベートしてから、Argon2付きでpwdlibをインストールしてください。 +[仮想環境](../../virtual-environments.md)を作成し、アクティベートしてから、Argon2付きでpwdlibをインストールしてください。
@@ -200,7 +200,7 @@ IDの衝突を回避するために、ユーザーのJWTトークンを作成す ## 確認 { #check-it } -サーバーを実行し、ドキュメントに移動します:http://127.0.0.1:8000/docs。 +サーバーを実行し、ドキュメントに移動します:[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 次のようなユーザーインターフェイスが表示されます: diff --git a/docs/ja/docs/tutorial/security/simple-oauth2.md b/docs/ja/docs/tutorial/security/simple-oauth2.md index c371b0acf6..842cd02e5b 100644 --- a/docs/ja/docs/tutorial/security/simple-oauth2.md +++ b/docs/ja/docs/tutorial/security/simple-oauth2.md @@ -146,7 +146,7 @@ UserInDB( /// info | 情報 -`**user_dict` のより完全な解説は、[**追加モデル**のドキュメント](../extra-models.md#about-user-in-dict){.internal-link target=_blank}を参照してください。 +`**user_dict` のより完全な解説は、[**追加モデル**のドキュメント](../extra-models.md#about-user-in-dict)を参照してください。 /// @@ -188,7 +188,7 @@ UserInDB( アクティブなユーザーの場合にのみ `current_user` を取得したいとします。 -そこで、`get_current_user` を依存関係として利用する追加の依存関係 `get_current_active_user` を作成します。 +そこで、`get_current_active_user` を依存関係として利用する追加の依存関係 `get_current_active_user` を作成します。 これら2つの依存関係は、ユーザーが存在しない、または非アクティブである場合に、HTTPエラーを返すだけです。 @@ -216,7 +216,7 @@ HTTP(エラー)ステータスコード 401「UNAUTHORIZED」は、`WWW-Auth ## 動作確認 { #see-it-in-action } -インタラクティブドキュメントを開きます: http://127.0.0.1:8000/docs。 +インタラクティブドキュメントを開きます: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 ### 認証 { #authenticate } diff --git a/docs/ja/docs/tutorial/sql-databases.md b/docs/ja/docs/tutorial/sql-databases.md index 930e433de4..13c71fdb2a 100644 --- a/docs/ja/docs/tutorial/sql-databases.md +++ b/docs/ja/docs/tutorial/sql-databases.md @@ -2,9 +2,9 @@ FastAPI は SQL(リレーショナル)データベースの使用を必須にはしません。必要であれば、任意のデータベースを使用できます。 -ここでは SQLModel を使った例を見ていきます。 +ここでは [SQLModel](https://sqlmodel.tiangolo.com/) を使った例を見ていきます。 -SQLModel は SQLAlchemy と Pydantic の上に構築されています。FastAPI と同じ作者により、SQL データベースを使う必要がある FastAPI アプリに最適になるように作られています。 +SQLModel は [SQLAlchemy](https://www.sqlalchemy.org/) と Pydantic の上に構築されています。FastAPI と同じ作者により、SQL データベースを使う必要がある FastAPI アプリに最適になるように作られています。 /// tip | 豆知識 @@ -26,15 +26,15 @@ SQLModel は SQLAlchemy をベースにしているため、SQLAlchemy がサポ /// tip | 豆知識 -フロントエンドやその他のツールを含む、FastAPI と PostgreSQL の公式プロジェクトジェネレーターがあります: https://github.com/fastapi/full-stack-fastapi-template +フロントエンドやその他のツールを含む、FastAPI と PostgreSQL の公式プロジェクトジェネレーターがあります: [https://github.com/fastapi/full-stack-fastapi-template](https://github.com/fastapi/full-stack-fastapi-template) /// -これはとてもシンプルで短いチュートリアルです。データベースや SQL、より高度な機能について学びたい場合は、SQLModel のドキュメントをご覧ください。 +これはとてもシンプルで短いチュートリアルです。データベースや SQL、より高度な機能について学びたい場合は、[SQLModel のドキュメント](https://sqlmodel.tiangolo.com/)をご覧ください。 ## `SQLModel` のインストール { #install-sqlmodel } -まずは [仮想環境](../virtual-environments.md){.internal-link target=_blank} を作成・有効化し、`sqlmodel` をインストールします: +まずは [仮想環境](../virtual-environments.md) を作成・有効化し、`sqlmodel` をインストールします:
@@ -65,7 +65,7 @@ $ pip install sqlmodel * `Field(primary_key=True)` は `id` が SQL データベースのプライマリキーであることを SQLModel に伝えます(SQL のプライマリキーについては SQLModel ドキュメントを参照してください)。 - 注: プライマリキーのフィールドには `int | None` を使っています。これは Python コード内で `id=None` のように「`id` なしでオブジェクトを作成」し、保存時にデータベースが生成することを想定するためです。SQLModel はデータベースが `id` を提供することを理解し、スキーマでは「NULL 不可の `INTEGER` 列」を定義します。詳細は SQLModel のプライマリキーに関するドキュメント を参照してください。 + 注: プライマリキーのフィールドには `int | None` を使っています。これは Python コード内で `id=None` のように「`id` なしでオブジェクトを作成」し、保存時にデータベースが生成することを想定するためです。SQLModel はデータベースが `id` を提供することを理解し、スキーマでは「NULL 不可の `INTEGER` 列」を定義します。詳細は [SQLModel のプライマリキーに関するドキュメント](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id) を参照してください。 * `Field(index=True)` は、この列に対して SQL のインデックスを作成するよう SQLModel に指示します。これにより、この列でフィルタしてデータを読む場合に検索が高速になります。 @@ -111,7 +111,7 @@ SQLModel の `engine`(内部的には SQLAlchemy の `engine`)は、デー /// tip | 豆知識 -SQLModel は Alembic をラップしたマイグレーションユーティリティを提供予定ですが、現時点では Alembic を直接使えます。 +SQLModel は Alembic をラップしたマイグレーションユーティリティを提供予定ですが、現時点では [Alembic](https://alembic.sqlalchemy.org/en/latest/) を直接使えます。 /// @@ -152,7 +152,7 @@ SQLModel は Alembic をラップしたマイグレーションユーティリ
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -337,7 +337,7 @@ SQLModel では継承を使って、あらゆるケースでフィールドの
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -352,6 +352,6 @@ $ fastapi dev main.py ## まとめ { #recap } -SQLModel を使って SQL データベースとやり取りし、データモデルとテーブルモデルでコードを簡潔にできます。 +[SQLModel](https://sqlmodel.tiangolo.com/) を使って SQL データベースとやり取りし、データモデルとテーブルモデルでコードを簡潔にできます。 -さらに多くを学ぶには SQLModel のドキュメントをご覧ください。FastAPI と SQLModel を使うチュートリアル もあります。🚀 +さらに多くを学ぶには SQLModel のドキュメントをご覧ください。[FastAPI と SQLModel を使うチュートリアル](https://sqlmodel.tiangolo.com/tutorial/fastapi/) もあります。🚀 diff --git a/docs/ja/docs/tutorial/static-files.md b/docs/ja/docs/tutorial/static-files.md index 52e28d6b05..81f281c2eb 100644 --- a/docs/ja/docs/tutorial/static-files.md +++ b/docs/ja/docs/tutorial/static-files.md @@ -23,7 +23,7 @@ これは、マウントされたアプリケーションが完全に独立しているため、`APIRouter` とは異なります。メインアプリケーションのOpenAPIとドキュメントには、マウントされたアプリケーションの内容などは含まれません。 -これについて詳しくは、[高度なユーザーガイド](../advanced/index.md){.internal-link target=_blank} をご覧ください。 +これについて詳しくは、[高度なユーザーガイド](../advanced/index.md) をご覧ください。 ## 詳細 { #details } @@ -37,4 +37,4 @@ ## より詳しい情報 { #more-info } -詳細とオプションについては、Starletteの静的ファイルに関するドキュメントを確認してください。 +詳細とオプションについては、[Starletteの静的ファイルに関するドキュメント](https://www.starlette.dev/staticfiles/)を確認してください。 diff --git a/docs/ja/docs/tutorial/testing.md b/docs/ja/docs/tutorial/testing.md index b09f1af723..0277d73b74 100644 --- a/docs/ja/docs/tutorial/testing.md +++ b/docs/ja/docs/tutorial/testing.md @@ -1,18 +1,18 @@ # テスト { #testing } -Starlette のおかげで、**FastAPI** アプリケーションのテストは簡単で楽しいものになっています。 +[Starlette](https://www.starlette.dev/testclient/) のおかげで、**FastAPI** アプリケーションのテストは簡単で楽しいものになっています。 -HTTPX がベースで、さらにその設計は Requests をベースにしているため、とても馴染みがあり直感的です。 +[HTTPX](https://www.python-httpx.org) がベースで、さらにその設計は Requests をベースにしているため、とても馴染みがあり直感的です。 -これを使用すると、**FastAPI** と共に pytest を直接利用できます。 +これを使用すると、**FastAPI** と共に [pytest](https://docs.pytest.org/) を直接利用できます。 ## `TestClient` を使用 { #using-testclient } -/// info | 情報 +/// info -`TestClient` を使用するには、まず `httpx` をインストールします。 +`TestClient` を使用するには、まず [`httpx`](https://www.python-httpx.org) をインストールします。 -[仮想環境](../virtual-environments.md){.internal-link target=_blank} を作成し、それを有効化してから、例えば以下のようにインストールしてください: +[仮想環境](../virtual-environments.md) を作成し、それを有効化してから、例えば以下のようにインストールしてください: ```console $ pip install httpx @@ -32,7 +32,7 @@ $ pip install httpx {* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} -/// tip | 豆知識 +/// tip テスト関数は `async def` ではなく、通常の `def` であることに注意してください。 @@ -50,9 +50,9 @@ $ pip install httpx /// -/// tip | 豆知識 +/// tip -FastAPIアプリケーションへのリクエストの送信とは別に、テストで `async` 関数 (非同期データベース関数など) を呼び出したい場合は、高度なチュートリアルの[Async Tests](../advanced/async-tests.md){.internal-link target=_blank} を参照してください。 +FastAPIアプリケーションへのリクエストの送信とは別に、テストで `async` 関数 (非同期データベース関数など) を呼び出したい場合は、高度なチュートリアルの[Async Tests](../advanced/async-tests.md) を参照してください。 /// @@ -64,7 +64,7 @@ FastAPIアプリケーションへのリクエストの送信とは別に、テ ### **FastAPI** アプリファイル { #fastapi-app-file } -[Bigger Applications](bigger-applications.md){.internal-link target=_blank} で説明されている、次のようなファイル構成があるとします: +[Bigger Applications](bigger-applications.md) で説明されている、次のようなファイル構成があるとします: ``` . @@ -142,13 +142,13 @@ FastAPIアプリケーションへのリクエストの送信とは別に、テ * *ヘッダー* を渡すには、`headers` パラメータに `dict` を渡します。 * *cookies* の場合、 `cookies` パラメータに `dict` です。 -(`httpx` または `TestClient` を使用して) バックエンドにデータを渡す方法の詳細は、HTTPXのドキュメントを確認してください。 +(`httpx` または `TestClient` を使用して) バックエンドにデータを渡す方法の詳細は、[HTTPXのドキュメント](https://www.python-httpx.org)を確認してください。 -/// info | 情報 +/// info `TestClient` は、Pydanticモデルではなく、JSONに変換できるデータを受け取ることに注意してください。 -テストにPydanticモデルがあり、テスト中にそのデータをアプリケーションに送信したい場合は、[JSON互換エンコーダ](encoder.md){.internal-link target=_blank} で説明されている `jsonable_encoder` が利用できます。 +テストにPydanticモデルがあり、テスト中にそのデータをアプリケーションに送信したい場合は、[JSON互換エンコーダ](encoder.md) で説明されている `jsonable_encoder` が利用できます。 /// @@ -156,7 +156,7 @@ FastAPIアプリケーションへのリクエストの送信とは別に、テ その後、`pytest` をインストールするだけです。 -[仮想環境](../virtual-environments.md){.internal-link target=_blank} を作成し、それを有効化してから、例えば以下のようにインストールしてください: +[仮想環境](../virtual-environments.md) を作成し、それを有効化してから、例えば以下のようにインストールしてください:
diff --git a/docs/ja/docs/virtual-environments.md b/docs/ja/docs/virtual-environments.md index 94af6ddae2..21b7cd4727 100644 --- a/docs/ja/docs/virtual-environments.md +++ b/docs/ja/docs/virtual-environments.md @@ -21,7 +21,7 @@ Pythonプロジェクトの作業では、**仮想環境**(または類似の /// info | 情報 このページでは、**仮想環境**の使用方法と、そのはたらきについて説明します。 -もし**すべてを管理するツール**(Pythonのインストールも含む)を導入する準備ができているなら、uv をお試しください。 +もし**すべてを管理するツール**(Pythonのインストールも含む)を導入する準備ができているなら、[uv](https://github.com/astral-sh/uv) をお試しください。 /// @@ -83,7 +83,7 @@ $ python -m venv .venv //// tab | `uv` -もし `uv` をインストール済みなら、仮想環境を作成するために `uv` を使うこともできます。 +もし [`uv`](https://github.com/astral-sh/uv) をインストール済みなら、仮想環境を作成するために `uv` を使うこともできます。
@@ -147,7 +147,7 @@ $ .venv\Scripts\Activate.ps1 //// tab | Windows Bash -もしWindowsでBashを使用している場合 (Git Bashなど): +もしWindowsでBashを使用している場合 ([Git Bash](https://gitforwindows.org/)など):
@@ -213,7 +213,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python /// tip | 豆知識 -もし `uv` を使用している場合は、 `pip` の代わりに `uv` を使ってインストールを行うため、 `pip` をアップグレードする必要はありません 😎。 +もし [`uv`](https://github.com/astral-sh/uv) を使用している場合は、 `pip` の代わりに `uv` を使ってインストールを行うため、 `pip` をアップグレードする必要はありません 😎。 /// @@ -265,7 +265,7 @@ $ python -m ensurepip --upgrade /// tip | 豆知識 -もし `uv` を使用して仮想環境を作成した場合、すでにこの作業は済んでいるので、この手順をスキップできます 😎。 +もし [`uv`](https://github.com/astral-sh/uv) を使用して仮想環境を作成した場合、すでにこの作業は済んでいるので、この手順をスキップできます 😎。 /// @@ -337,7 +337,7 @@ $ pip install "fastapi[standard]" //// tab | `uv` -もし `uv` を使用できるなら: +もし [`uv`](https://github.com/astral-sh/uv) を使用できるなら:
@@ -369,7 +369,7 @@ $ pip install -r requirements.txt //// tab | `uv` -もし `uv` を使用できるなら: +もし [`uv`](https://github.com/astral-sh/uv) を使用できるなら:
@@ -413,8 +413,8 @@ Hello World 設定例: -* VS Code -* PyCharm +* [VS Code](https://code.visualstudio.com/docs/python/environments#_select-and-activate-an-environment) +* [PyCharm](https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html) /// tip | 豆知識 @@ -452,7 +452,7 @@ $ deactivate ## なぜ仮想環境? { #why-virtual-environments } -FastAPIを使った作業をするには、Python のインストールが必要です。 +FastAPIを使った作業をするには、[Python](https://www.python.org/) のインストールが必要です。 それから、FastAPIや、使用したいその他の**パッケージ**を**インストール**する必要があります。 @@ -561,7 +561,7 @@ $ pip install "fastapi[standard]"
-FastAPIのコードを含む圧縮ファイルが、通常は PyPI からダウンロードされます。 +FastAPIのコードを含む圧縮ファイルが、通常は [PyPI](https://pypi.org/project/fastapi/) からダウンロードされます。 また、FastAPIが依存する他のパッケージも**ダウンロード**されます。 @@ -624,7 +624,7 @@ $ .venv\Scripts\Activate.ps1 //// tab | Windows Bash -あるいは、WindowsでBashを使用している場合 (Git Bashなど): +あるいは、WindowsでBashを使用している場合 ([Git Bash](https://gitforwindows.org/)など):
@@ -636,13 +636,13 @@ $ source .venv/Scripts/activate //// -これによって、いくつかの [環境変数](environment-variables.md){.internal-link target=_blank} が作成・修正され、次に実行されるコマンドで使用できるようになります。 +これによって、いくつかの [環境変数](environment-variables.md) が作成・修正され、次に実行されるコマンドで使用できるようになります。 これらの環境変数のひとつに、 `PATH` 変数があります。 /// tip | 豆知識 -`PATH` 変数についての詳細は [環境変数](environment-variables.md#path-environment-variable){.internal-link target=_blank} を参照してください。 +`PATH` 変数についての詳細は [環境変数](environment-variables.md#path-environment-variable) を参照してください。 /// @@ -835,7 +835,7 @@ I solemnly swear 🐺 仮想環境、パッケージの依存関係(requirements)、プロジェクトの管理には、多くの**代替手段**があります。 -準備が整い、パッケージの依存関係、仮想環境など**プロジェクト全体の管理**ツールを使いたいと考えたら、uv を試してみることをおすすめします。 +準備が整い、パッケージの依存関係、仮想環境など**プロジェクト全体の管理**ツールを使いたいと考えたら、[uv](https://github.com/astral-sh/uv) を試してみることをおすすめします。 `uv` では以下のような多くのことができます: From b4f81b40a8f851f36f6a85b8be79002c38a3f50b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Mar 2026 14:07:59 +0000 Subject: [PATCH 04/69] =?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 d9bb22b7b3..0f55927585 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Translations +* 🌐 Update translations for ja (update-outdated). PR [#15171](https://github.com/fastapi/fastapi/pull/15171) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (update-outdated). PR [#15170](https://github.com/fastapi/fastapi/pull/15170) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for tr (update-outdated). PR [#15172](https://github.com/fastapi/fastapi/pull/15172) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (add-missing). PR [#15168](https://github.com/fastapi/fastapi/pull/15168) by [@tiangolo](https://github.com/tiangolo). From 5ef5490bc4fcacbf9d1a982b8538ab9ccec8abeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 20 Mar 2026 15:29:48 +0100 Subject: [PATCH 05/69] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20fo?= =?UTF-8?q?r=20zh=20(add-missing)=20(#15175)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/zh/docs/advanced/json-base64-bytes.md | 63 ++++++++++ docs/zh/docs/advanced/stream-data.md | 117 ++++++++++++++++++ docs/zh/docs/advanced/strict-content-type.md | 88 ++++++++++++++ docs/zh/docs/editor-support.md | 23 ++++ docs/zh/docs/tutorial/server-sent-events.md | 120 +++++++++++++++++++ docs/zh/docs/tutorial/stream-json-lines.md | 111 +++++++++++++++++ 6 files changed, 522 insertions(+) create mode 100644 docs/zh/docs/advanced/json-base64-bytes.md create mode 100644 docs/zh/docs/advanced/stream-data.md create mode 100644 docs/zh/docs/advanced/strict-content-type.md create mode 100644 docs/zh/docs/editor-support.md create mode 100644 docs/zh/docs/tutorial/server-sent-events.md create mode 100644 docs/zh/docs/tutorial/stream-json-lines.md diff --git a/docs/zh/docs/advanced/json-base64-bytes.md b/docs/zh/docs/advanced/json-base64-bytes.md new file mode 100644 index 0000000000..7792282c72 --- /dev/null +++ b/docs/zh/docs/advanced/json-base64-bytes.md @@ -0,0 +1,63 @@ +# 在 JSON 中使用 Base64 表示字节 { #json-with-bytes-as-base64 } + +如果你的应用需要接收和发送 JSON 数据,但其中需要包含二进制数据,可以将其编码为 base64。 + +## Base64 与文件 { #base64-vs-files } + +请先考虑是否可以使用 [请求文件](../tutorial/request-files.md) 来上传二进制数据,并使用 [自定义响应 - FileResponse](./custom-response.md#fileresponse--fileresponse-) 来发送二进制数据,而不是把它编码进 JSON。 + +JSON 只能包含 UTF-8 编码的字符串,因此无法直接包含原始字节。 + +Base64 可以把二进制数据编码为字符串,但为此会使用比原始二进制更多的字符,因此通常比直接使用文件的效率更低。 + +仅当你确实需要在 JSON 中包含二进制数据且无法使用文件时,才使用 base64。 + +## Pydantic `bytes` { #pydantic-bytes } + +你可以声明带有 `bytes` 字段的 Pydantic 模型,然后在模型配置中使用 `val_json_bytes` 指定用 base64 来验证输入的 JSON 数据;作为验证的一部分,它会将该 base64 字符串解码为字节。 + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} + +查看 `/docs` 时,你会看到字段 `data` 期望接收 base64 编码的字节: + +
+ +
+ +你可以发送如下请求: + +```json +{ + "description": "Some data", + "data": "aGVsbG8=" +} +``` + +/// tip | 提示 + +`aGVsbG8=` 是 `hello` 的 base64 编码。 + +/// + +随后 Pydantic 会解码该 base64 字符串,并在模型的 `data` 字段中提供原始字节。 + +你将会收到类似的响应: + +```json +{ + "description": "Some data", + "content": "hello" +} +``` + +## 用于输出数据的 Pydantic `bytes` { #pydantic-bytes-for-output-data } + +对于输出数据,你也可以在模型配置中为 `bytes` 字段使用 `ser_json_bytes`,Pydantic 会在生成 JSON 响应时将字节以 base64 进行序列化。 + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} + +## 用于输入和输出数据的 Pydantic `bytes` { #pydantic-bytes-for-input-and-output-data } + +当然,你也可以使用同一个配置了 base64 的模型,在接收和发送 JSON 数据时,同时处理输入(使用 `val_json_bytes` 进行验证)和输出(使用 `ser_json_bytes` 进行序列化)。 + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/zh/docs/advanced/stream-data.md b/docs/zh/docs/advanced/stream-data.md new file mode 100644 index 0000000000..322561ac11 --- /dev/null +++ b/docs/zh/docs/advanced/stream-data.md @@ -0,0 +1,117 @@ +# 流式数据 { #stream-data } + +如果你要流式传输可以结构化为 JSON 的数据,你应该[流式传输 JSON Lines](../tutorial/stream-json-lines.md)。 + +但如果你想流式传输纯二进制数据或字符串,可以按下面的方法操作。 + +/// info | 信息 + +自 FastAPI 0.134.0 起新增。 + +/// + +## 使用场景 { #use-cases } + +如果你想流式传输纯字符串,例如直接来自某个 AI LLM 服务的输出,可以使用它。 + +你也可以用它来流式传输大型二进制文件,在读取的同时按块发送,无需一次性把所有内容读入内存。 + +你还可以用这种方式流式传输视频或音频,甚至可以在处理的同时生成并发送。 + +## 使用 `yield` 的 `StreamingResponse` { #a-streamingresponse-with-yield } + +如果你在*路径操作函数*中声明 `response_class=StreamingResponse`,你就可以使用 `yield` 依次发送每个数据块。 + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} + +FastAPI 会将每个数据块原样交给 `StreamingResponse`,不会尝试将其转换为 JSON 或做类似处理。 + +### 非 async 的*路径操作函数* { #non-async-path-operation-functions } + +你也可以使用常规的 `def` 函数(不带 `async`),并以相同方式使用 `yield`。 + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[26:29] hl[27] *} + +### 无需注解 { #no-annotation } + +你其实不需要为流式二进制数据声明返回类型注解。 + +由于 FastAPI 不会使用 Pydantic 将数据转换为 JSON,也不会以任何方式序列化,在这种情况下,类型注解只供你的编辑器和工具使用,FastAPI 不会使用它。 + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} + +这也意味着,使用 `StreamingResponse` 时,你拥有按需精确生成与编码字节数据的自由,同时也承担相应的责任,它与类型注解无关。🤓 + +### 流式传输字节 { #stream-bytes } + +主要的用例之一是流式传输 `bytes` 而不是字符串,这当然可以做到。 + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[44:47] hl[47] *} + +## 自定义 `PNGStreamingResponse` { #a-custom-pngstreamingresponse } + +在上面的示例中,虽然按字节流式传输了数据,但响应没有 `Content-Type` 头,因此客户端不知道接收到的数据类型。 + +你可以创建 `StreamingResponse` 的自定义子类,将 `Content-Type` 头设置为你要流式传输的数据类型。 + +例如,你可以创建一个 `PNGStreamingResponse`,通过 `media_type` 属性把 `Content-Type` 头设置为 `image/png`: + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} + +然后你可以在*路径操作函数*中通过 `response_class=PNGStreamingResponse` 使用这个新类: + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} + +### 模拟文件 { #simulate-a-file } + +在这个示例中,我们用 `io.BytesIO` 模拟了一个文件,它是只驻留在内存中的类文件对象,但提供相同的接口。 + +例如,我们可以像对文件那样迭代它来消费其内容。 + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[1:27] hl[3,12:13,25] *} + +/// note | 技术细节 + +另外两个变量 `image_base64` 和 `binary_image` 表示一张图像,先用 Base64 编码,再转换为 bytes,最后传给 `io.BytesIO`。 + +只是为了让它们能和示例放在同一个文件里,便于你直接复制运行。🥚 + +/// + +通过使用 `with` 代码块,我们确保在生成器函数(带有 `yield` 的函数)完成后关闭这个类文件对象。也就是在发送完响应之后。 + +在这个特定示例中这并不那么重要,因为它是一个内存中的假文件(使用 `io.BytesIO`),但对于真实文件,确保在完成相关工作后关闭文件是很重要的。 + +### 文件与异步 { #files-and-async } + +大多数情况下,类文件对象默认与 async 和 await 不兼容。 + +例如,它们没有 `await file.read()`,也不支持 `async for chunk in file`。 + +而且很多情况下,读取它们是一个阻塞操作(可能会阻塞事件循环),因为数据来自磁盘或网络。 + +/// info | 信息 + +上面的示例其实是个例外,因为 `io.BytesIO` 对象已经在内存中,所以读取它不会阻塞。 + +但在许多情况下,读取文件或类文件对象会发生阻塞。 + +/// + +为避免阻塞事件循环,你可以简单地把*路径操作函数*声明为常规的 `def`(而不是 `async def`),这样 FastAPI 会在一个线程池工作线程上运行它,从而避免阻塞主事件循环。 + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} + +/// tip | 提示 + +如果你需要在异步函数里调用阻塞代码,或在阻塞函数里调用异步函数,可以使用 [Asyncer](https://asyncer.tiangolo.com),它是 FastAPI 的姐妹库。 + +/// + +### `yield from` { #yield-from } + +当你在迭代某个对象(例如类文件对象),并为每个条目执行 `yield` 时,你也可以使用 `yield from` 直接产出每个条目,从而省去 `for` 循环。 + +这并不是 FastAPI 特有的功能,只是 Python 的语法,但这是一个值得知道的小技巧。😎 + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[37:40] hl[40] *} diff --git a/docs/zh/docs/advanced/strict-content-type.md b/docs/zh/docs/advanced/strict-content-type.md new file mode 100644 index 0000000000..973d1840c0 --- /dev/null +++ b/docs/zh/docs/advanced/strict-content-type.md @@ -0,0 +1,88 @@ +# 严格的 Content-Type 检查 { #strict-content-type-checking } + +默认情况下,FastAPI 对 JSON 请求体使用严格的 `Content-Type` 头检查。这意味着,JSON 请求必须包含有效的 `Content-Type` 头(例如 `application/json`),其请求体才会被按 JSON 解析。 + +## CSRF 风险 { #csrf-risk } + +此默认行为在一个非常特定的场景下,可防御一类跨站请求伪造(CSRF)攻击。 + +这类攻击利用了浏览器的一个事实:当请求满足以下条件时,浏览器允许脚本在不进行任何 CORS 预检的情况下直接发送请求: + +- 没有 `Content-Type` 头(例如使用 `fetch()` 携带 `Blob` 作为 body) +- 且不发送任何认证凭据。 + +这种攻击主要在以下情况下相关: + +- 应用在本地(如 `localhost`)或内网中运行 +- 且应用没有任何认证,假定来自同一网络的请求都可信。 + +## 攻击示例 { #example-attack } + +假设你构建了一个本地运行的 AI 代理。 + +它提供了一个 API,地址为 + +``` +http://localhost:8000/v1/agents/multivac +``` + +另有一个前端,地址为 + +``` +http://localhost:8000 +``` + +/// tip | 提示 + +注意它们的主机相同。 + +/// + +之后,你可以通过前端让该 AI 代理替你执行操作。 + +由于它在本地运行、而非暴露在开放的互联网,你决定不配置任何认证,只信任对本地网络的访问。 + +于是,你的某位用户安装并在本地运行了它。 + +然后他(她)可能会打开一个恶意网站,例如 + +``` +https://evilhackers.example.com +``` + +该恶意网站使用 `fetch()` 携带 `Blob` 作为 body,向本地 API 发送请求,地址为 + +``` +http://localhost:8000/v1/agents/multivac +``` + +尽管恶意网站与本地应用的主机不同,浏览器仍不会触发 CORS 预检请求,原因是: + +- 请求不涉及任何认证,无需发送凭据。 +- 浏览器认为它并未发送 JSON(因为缺少 `Content-Type` 头)。 + +于是,该恶意网站就可能让本地 AI 代理替用户向前老板发送愤怒消息……甚至更糟。😅 + +## 开放的互联网 { #open-internet } + +如果你的应用部署在开放的互联网,你不会“信任网络”,也不会允许任何人不经认证就发送特权请求。 + +攻击者完全可以直接运行脚本向你的 API 发送请求,无需借助浏览器交互,因此你很可能已经对任何特权端点做好了安全防护。 + +在这种情况下,以上攻击/风险不适用于你。 + +该风险/攻击主要发生在应用运行于本地网络、且“仅依赖网络隔离作为保护”的场景。 + +## 允许无 Content-Type 的请求 { #allowing-requests-without-content-type } + +如果你需要兼容不发送 `Content-Type` 头的客户端,可以通过设置 `strict_content_type=False` 来关闭严格检查: + +{* ../../docs_src/strict_content_type/tutorial001_py310.py hl[4] *} + +启用该设置后,缺少 `Content-Type` 头的请求其请求体也会按 JSON 解析,这与旧版本 FastAPI 的行为一致。 + +/// info | 信息 + +此行为和配置在 FastAPI 0.132.0 中新增。 + +/// diff --git a/docs/zh/docs/editor-support.md b/docs/zh/docs/editor-support.md new file mode 100644 index 0000000000..5028c6c957 --- /dev/null +++ b/docs/zh/docs/editor-support.md @@ -0,0 +1,23 @@ +# 编辑器支持 { #editor-support } + +官方的 [FastAPI 扩展](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode)为你的 FastAPI 开发流程带来增强,包括*路径操作*的发现与导航、部署到 FastAPI Cloud,以及实时日志流式传输。 + +有关该扩展的更多详情,请参阅其 [GitHub 仓库](https://github.com/fastapi/fastapi-vscode)中的 README。 + +## 安装与配置 { #setup-and-installation } + +**FastAPI 扩展**同时适用于 [VS Code](https://code.visualstudio.com/) 和 [Cursor](https://www.cursor.com/)。你可以在各编辑器的扩展面板中直接搜索 “FastAPI”,并选择由 **FastAPI Labs** 发布的扩展进行安装。该扩展也适用于基于浏览器的编辑器,例如 [vscode.dev](https://vscode.dev) 和 [github.dev](https://github.dev)。 + +### 应用发现 { #application-discovery } + +默认情况下,扩展会通过扫描实例化了 `FastAPI()` 的文件,自动发现工作区中的 FastAPI 应用。如果你的项目结构无法自动检测,你可以通过 `pyproject.toml` 中的 `[tool.fastapi]` 或 VS Code 设置项 `fastapi.entryPoint` 来指定入口点,使用模块表示法(例如 `myapp.main:app`)。 + +## 功能 { #features } + +- **Path Operation 资源管理器** - 侧边栏树状视图展示应用中的所有 *路径操作*。点击可跳转至任一路由或 APIRouter 的定义。 +- **路由搜索** - 使用 Ctrl + Shift + E(macOS 上为 Cmd + Shift + E)按路径、方法或名称进行搜索。 +- **CodeLens 导航** - 测试客户端调用(例如 `client.get('/items')`)上方的可点击链接,可跳转到匹配的*路径操作*,在测试与实现之间快速往返。 +- **部署到 FastAPI Cloud** - 一键将你的应用部署到 [FastAPI Cloud](https://fastapicloud.com/)。 +- **应用日志流式传输** - 从部署在 FastAPI Cloud 的应用中实时流式获取日志,并支持按级别过滤与文本搜索。 + +如果你想先熟悉扩展功能,可以打开命令面板(Ctrl + Shift + P,macOS 上为 Cmd + Shift + P),选择 “Welcome: Open walkthrough...”,然后选择 “Get started with FastAPI” 演练。 diff --git a/docs/zh/docs/tutorial/server-sent-events.md b/docs/zh/docs/tutorial/server-sent-events.md new file mode 100644 index 0000000000..c78562b91e --- /dev/null +++ b/docs/zh/docs/tutorial/server-sent-events.md @@ -0,0 +1,120 @@ +# 服务器发送事件(SSE) { #server-sent-events-sse } + +你可以使用**服务器发送事件**(SSE)向客户端流式发送数据。 + +这类似于[流式传输 JSON Lines](stream-json-lines.md),但使用 `text/event-stream` 格式,浏览器原生通过 [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) 支持。 + +/// info | 信息 + +新增于 FastAPI 0.135.0。 + +/// + +## 什么是服务器发送事件? { #what-are-server-sent-events } + +SSE 是一种通过 HTTP 从服务器向客户端流式传输数据的标准。 + +每个事件是一个带有 `data`、`event`、`id` 和 `retry` 等“字段”的小文本块,以空行分隔。 + +看起来像这样: + +``` +data: {"name": "Portal Gun", "price": 999.99} + +data: {"name": "Plumbus", "price": 32.99} + +``` + +SSE 常用于 AI 聊天流式输出、实时通知、日志与可观测性,以及其他服务器向客户端推送更新的场景。 + +/// tip | 提示 + +如果你想流式传输二进制数据(例如视频或音频),请查看高级指南:[流式传输数据](../advanced/stream-data.md)。 + +/// + +## 使用 FastAPI 流式传输 SSE { #stream-sse-with-fastapi } + +要在 FastAPI 中流式传输 SSE,在你的*路径操作函数*中使用 `yield`,并设置 `response_class=EventSourceResponse`。 + +从 `fastapi.sse` 导入 `EventSourceResponse`: + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[4,22] *} + +每个被 yield 的项会被编码为 JSON,并放入 SSE 事件的 `data:` 字段发送。 + +如果你将返回类型声明为 `AsyncIterable[Item]`,FastAPI 将使用它通过 Pydantic对数据进行**校验**、**文档化**和**序列化**。 + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[10:12,23] *} + +/// tip | 提示 + +由于 Pydantic 会在**Rust** 端序列化它,相比未声明返回类型,你将获得更高的**性能**。 + +/// + +### 非 async 的*路径操作函数* { #non-async-path-operation-functions } + +你也可以使用常规的 `def` 函数(没有 `async`),并以同样的方式使用 `yield`。 + +FastAPI 会确保其正确运行,从而不阻塞事件循环。 + +由于此时函数不是 async,正确的返回类型应为 `Iterable[Item]`: + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[28:31] hl[29] *} + +### 无返回类型 { #no-return-type } + +你也可以省略返回类型。FastAPI 将使用 [`jsonable_encoder`](./encoder.md) 转换数据并发送。 + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[34:37] hl[35] *} + +## `ServerSentEvent` { #serversentevent } + +如果你需要设置 `event`、`id`、`retry` 或 `comment` 等 SSE 字段,你可以 yield `ServerSentEvent` 对象,而不是直接返回数据。 + +从 `fastapi.sse` 导入 `ServerSentEvent`: + +{* ../../docs_src/server_sent_events/tutorial002_py310.py hl[4,26] *} + +`data` 字段始终会被编码为 JSON。你可以传入任何可被序列化为 JSON 的值,包括 Pydantic 模型。 + +## 原始数据 { #raw-data } + +如果你需要发送**不**进行 JSON 编码的数据,请使用 `raw_data` 而不是 `data`。 + +这对于发送预格式化文本、日志行或特殊的 "哨兵" 值(例如 `[DONE]`)很有用。 + +{* ../../docs_src/server_sent_events/tutorial003_py310.py hl[17] *} + +/// note | 注意 + +`data` 和 `raw_data` 是互斥的。每个 `ServerSentEvent` 上只能设置其中一个。 + +/// + +## 使用 `Last-Event-ID` 恢复 { #resuming-with-last-event-id } + +当连接中断后浏览器重新连接时,会在 `Last-Event-ID` 头中发送上次收到的 `id`。 + +你可以将其读取为一个请求头参数,并据此从客户端离开的地方恢复流: + +{* ../../docs_src/server_sent_events/tutorial004_py310.py hl[25,27,31] *} + +## 使用 POST 的 SSE { #sse-with-post } + +SSE 适用于**任意 HTTP 方法**,不仅仅是 `GET`。 + +这对像 [MCP](https://modelcontextprotocol.io) 这样通过 `POST` 传输 SSE 的协议很有用: + +{* ../../docs_src/server_sent_events/tutorial005_py310.py hl[14] *} + +## 技术细节 { #technical-details } + +FastAPI 开箱即用地实现了一些 SSE 的最佳实践。 + +- 当 15 秒内没有任何消息时,发送一个**保活 `ping` 注释**,以防某些代理关闭连接,正如 [HTML 规范:Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes) 中建议的那样。 +- 设置 `Cache-Control: no-cache` 响应头,**防止缓存**流。 +- 设置特殊响应头 `X-Accel-Buffering: no`,以**防止**某些代理(如 Nginx)**缓冲**。 + +你无需做任何事,它开箱即用。🤓 diff --git a/docs/zh/docs/tutorial/stream-json-lines.md b/docs/zh/docs/tutorial/stream-json-lines.md new file mode 100644 index 0000000000..8a27dce760 --- /dev/null +++ b/docs/zh/docs/tutorial/stream-json-lines.md @@ -0,0 +1,111 @@ +# 流式传输 JSON Lines { #stream-json-lines } + +当你想以“流”的方式发送一系列数据时,可以使用 JSON Lines。 + +/// info | 信息 + +新增于 FastAPI 0.134.0。 + +/// + +## 什么是流 { #what-is-a-stream } + +“流式传输”数据意味着你的应用会在整段数据全部准备好之前,就开始把每个数据项发送给客户端。 + +也就是说,它会先发送第一个数据项,客户端会接收并开始处理它,而此时你的应用可能还在生成下一个数据项。 + +```mermaid +sequenceDiagram + participant App + participant Client + + App->>App: Produce Item 1 + App->>Client: Send Item 1 + App->>App: Produce Item 2 + Client->>Client: Process Item 1 + App->>Client: Send Item 2 + App->>App: Produce Item 3 + Client->>Client: Process Item 2 + App->>Client: Send Item 3 + Client->>Client: Process Item 3 + Note over App: Keeps producing... + Note over Client: Keeps consuming... +``` + +它甚至可以是一个无限流,你可以一直持续发送数据。 + +## JSON Lines { #json-lines } + +在这些场景中,常见的做法是发送 “JSON Lines”,这是一种每行发送一个 JSON 对象的格式。 + +响应的内容类型是 `application/jsonl`(而不是 `application/json`),响应体类似这样: + +```json +{"name": "Plumbus", "description": "A multi-purpose household device."} +{"name": "Portal Gun", "description": "A portal opening device."} +{"name": "Meeseeks Box", "description": "A box that summons a Meeseeks."} +``` + +它与 JSON 数组(相当于 Python 的 list)非常相似,但不是用 `[]` 包裹、并在各项之间使用 `,` 分隔,而是每行一个 JSON 对象,彼此以换行符分隔。 + +/// info | 信息 + +关键在于你的应用可以逐行生成数据,而客户端在消费前面的行。 + +/// + +/// note | 技术细节 + +由于每个 JSON 对象将以换行分隔,它们的内容中不能包含字面量换行符,但可以包含转义换行符(`\n`),这属于 JSON 标准的一部分。 + +不过通常你无需操心,这些都会自动完成,继续阅读即可。🤓 + +/// + +## 使用场景 { #use-cases } + +你可以用它来从 AI LLM 服务、日志或遥测中流式传输数据,或其他可以用 JSON 项目来结构化的数据。 + +/// tip | 提示 + +如果你想流式传输二进制数据,例如视频或音频,请查看进阶指南:[流式传输数据](../advanced/stream-data.md)。 + +/// + +## 使用 FastAPI 流式传输 JSON Lines { #stream-json-lines-with-fastapi } + +要在 FastAPI 中流式传输 JSON Lines,可以在路径操作函数中不用 `return`,而是用 `yield` 逐个产生每个数据项。 + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[24] *} + +如果你要返回的每个 JSON 项是类型 `Item`(一个 Pydantic 模型),并且这是一个异步函数,你可以将返回类型声明为 `AsyncIterable[Item]`: + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[9:11,22] *} + +如果你声明了返回类型,FastAPI 会用它来验证数据、在 OpenAPI 中生成文档、进行过滤,并使用 Pydantic 进行序列化。 + +/// tip | 提示 + +由于 Pydantic 会在 Rust 侧进行序列化,如果你声明了返回类型,将获得更高的性能。 + +/// + +### 非异步的*路径操作函数* { #non-async-path-operation-functions } + +你也可以使用常规的 `def` 函数(不带 `async`),并以同样的方式使用 `yield`。 + +FastAPI 会确保其正确运行,不会阻塞事件循环。 + +因为这个函数不是异步的,合适的返回类型是 `Iterable[Item]`: + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[27:30] hl[28] *} + +### 无返回类型 { #no-return-type } + +你也可以省略返回类型。此时 FastAPI 会使用 [`jsonable_encoder`](./encoder.md) 将数据转换为可序列化为 JSON 的形式,然后以 JSON Lines 发送。 + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[33:36] hl[34] *} + +## 服务器发送事件(SSE) { #server-sent-events-sse } + +FastAPI 还对 Server-Sent Events(SSE)提供一等支持,它们与此非常相似,但有一些额外细节。你可以在下一章了解更多:[服务器发送事件(SSE)](server-sent-events.md)。🤓 From 1122d37676ddf27256c315dde80e2e426670ae03 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Mar 2026 14:30:15 +0000 Subject: [PATCH 06/69] =?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 0f55927585..812a108c9e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Translations +* 🌐 Update translations for zh (add-missing). PR [#15175](https://github.com/fastapi/fastapi/pull/15175) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ja (update-outdated). PR [#15171](https://github.com/fastapi/fastapi/pull/15171) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (update-outdated). PR [#15170](https://github.com/fastapi/fastapi/pull/15170) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for tr (update-outdated). PR [#15172](https://github.com/fastapi/fastapi/pull/15172) by [@tiangolo](https://github.com/tiangolo). From df4417efa51e92485c5bbaadadeb1e2658ff440d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 20 Mar 2026 15:33:04 +0100 Subject: [PATCH 07/69] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20fo?= =?UTF-8?q?r=20zh-hant=20(add-missing)=20(#15176)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- .../docs/advanced/json-base64-bytes.md | 63 +++++++++ docs/zh-hant/docs/advanced/stream-data.md | 117 +++++++++++++++++ .../docs/advanced/strict-content-type.md | 88 +++++++++++++ docs/zh-hant/docs/editor-support.md | 23 ++++ .../docs/tutorial/server-sent-events.md | 120 ++++++++++++++++++ .../docs/tutorial/stream-json-lines.md | 111 ++++++++++++++++ 6 files changed, 522 insertions(+) create mode 100644 docs/zh-hant/docs/advanced/json-base64-bytes.md create mode 100644 docs/zh-hant/docs/advanced/stream-data.md create mode 100644 docs/zh-hant/docs/advanced/strict-content-type.md create mode 100644 docs/zh-hant/docs/editor-support.md create mode 100644 docs/zh-hant/docs/tutorial/server-sent-events.md create mode 100644 docs/zh-hant/docs/tutorial/stream-json-lines.md diff --git a/docs/zh-hant/docs/advanced/json-base64-bytes.md b/docs/zh-hant/docs/advanced/json-base64-bytes.md new file mode 100644 index 0000000000..9f1ecfa2ea --- /dev/null +++ b/docs/zh-hant/docs/advanced/json-base64-bytes.md @@ -0,0 +1,63 @@ +# 使用 Base64 表示位元組的 JSON { #json-with-bytes-as-base64 } + +如果你的應用需要收發 JSON 資料,但其中需要包含二進位資料,你可以將它以 base64 編碼。 + +## Base64 與檔案 { #base64-vs-files } + +請先考慮是否能用 [請求檔案](../tutorial/request-files.md) 來上傳二進位資料,並用 [自訂回應 - FileResponse](./custom-response.md#fileresponse--fileresponse-) 來傳送二進位資料,而不是把它們編碼進 JSON。 + +JSON 只能包含 UTF-8 編碼的字串,因此無法直接包含原始位元組。 + +Base64 可以把二進位資料編碼成字串,但為此會使用比原始二進位資料更多的字元,因此通常比直接使用檔案來得沒那麼有效率。 + +只有在確實必須把二進位資料包含在 JSON 裡,且無法改用檔案時,才使用 base64。 + +## Pydantic `bytes` { #pydantic-bytes } + +你可以宣告含有 `bytes` 欄位的 Pydantic 模型,並在模型設定中使用 `val_json_bytes`,使其在驗證輸入的 JSON 資料時使用 base64;在驗證過程中,它會將 base64 字串解碼為位元組。 + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} + +如果你查看 `/docs`,會看到欄位 `data` 需要 base64 編碼的位元組: + +
+ +
+ +你可以發送如下的請求: + +```json +{ + "description": "Some data", + "data": "aGVsbG8=" +} +``` + +/// tip + +`aGVsbG8=` 是 `hello` 的 base64 編碼。 + +/// + +接著 Pydantic 會將該 base64 字串解碼,並在模型的 `data` 欄位中提供原始位元組。 + +你會收到類似以下的回應: + +```json +{ + "description": "Some data", + "content": "hello" +} +``` + +## Pydantic `bytes` 用於輸出資料 { #pydantic-bytes-for-output-data } + +你也可以在模型設定中搭配 `ser_json_bytes` 使用 `bytes` 欄位來處理輸出資料;當產生 JSON 回應時,Pydantic 會將位元組以 base64 進行序列化。 + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} + +## Pydantic `bytes` 用於輸入與輸出資料 { #pydantic-bytes-for-input-and-output-data } + +當然,你也可以使用同一個以 base64 設定的模型,同時處理輸入(以 `val_json_bytes` 驗證)與輸出(以 `ser_json_bytes` 序列化)的 JSON 資料。 + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/zh-hant/docs/advanced/stream-data.md b/docs/zh-hant/docs/advanced/stream-data.md new file mode 100644 index 0000000000..0f55ae6516 --- /dev/null +++ b/docs/zh-hant/docs/advanced/stream-data.md @@ -0,0 +1,117 @@ +# 串流資料 { #stream-data } + +如果你要串流可用 JSON 結構化的資料,應該[串流 JSON Lines](../tutorial/stream-json-lines.md)。 + +但如果你想串流純二進位資料或字串,以下是做法。 + +/// info + +已在 FastAPI 0.134.0 新增。 + +/// + +## 使用情境 { #use-cases } + +當你想串流純字串時可以用這個機制,例如直接轉發來自 AI LLM 服務的輸出。 + +你也可以用它來串流大型二進位檔案,邊讀邊將每個區塊(chunk)串流出去,而不必一次把整個檔案載入記憶體。 + +你也可以用同樣方式串流視訊或音訊,甚至可以在處理的同時即時產生並傳送。 + +## 使用 `yield` 的 `StreamingResponse` { #a-streamingresponse-with-yield } + +如果在你的路徑操作函式中宣告 `response_class=StreamingResponse`,就可以用 `yield` 逐一送出每個資料區塊。 + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} + +FastAPI 會如實將每個資料區塊交給 `StreamingResponse`,不會嘗試將其轉換為 JSON 或其他格式。 + +### 非 async 路徑操作函式 { #non-async-path-operation-functions } + +你也可以使用一般的 `def` 函式(沒有 `async`),並以相同方式使用 `yield`。 + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[26:29] hl[27] *} + +### 不需要型別註解 { #no-annotation } + +對於串流二進位資料,其實不需要宣告回傳型別註解。 + +由於 FastAPI 不會試圖用 Pydantic 將資料轉成 JSON,或以其他方式序列化,在這種情況下,型別註解僅供編輯器與工具使用,FastAPI 並不會用到它。 + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} + +這也意味著使用 `StreamingResponse` 時,你擁有自由與責任,需依需求自行產生並編碼要傳送的位元組資料,與型別註解無關。 🤓 + +### 串流位元組 { #stream-bytes } + +一個主要用例是串流 `bytes` 而非字串,當然可以這麼做。 + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[44:47] hl[47] *} + +## 自訂 `PNGStreamingResponse` { #a-custom-pngstreamingresponse } + +在上述範例中,雖然串流了資料位元組,但回應沒有 `Content-Type` 標頭,因此用戶端不知道接收到的是哪種資料型別。 + +你可以建立 `StreamingResponse` 的自訂子類別,將 `Content-Type` 標頭設定為你要串流的資料型別。 + +例如,你可以建立 `PNGStreamingResponse`,透過 `media_type` 屬性把 `Content-Type` 設為 `image/png`: + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} + +接著在路徑操作函式中用 `response_class=PNGStreamingResponse` 使用這個新類別: + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} + +### 模擬檔案 { #simulate-a-file } + +此範例中我們用 `io.BytesIO` 模擬檔案。它是只存在於記憶體中的類檔案物件,但提供相同的介面。 + +例如,我們可以像讀取一般檔案一樣,透過迭代來消耗其內容。 + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[1:27] hl[3,12:13,25] *} + +/// note | 技術細節 + +另外兩個變數 `image_base64` 與 `binary_image`,分別是先將影像以 Base64 編碼,接著轉成位元組,最後再傳給 `io.BytesIO`。 + +這只是為了讓範例能放在同一個檔案中,方便你直接複製並執行。 🥚 + +/// + +使用 `with` 區塊可確保在產生器函式(包含 `yield` 的函式)完成後關閉該類檔案物件,也就是在送完回應之後。 + +在這個範例中因為是存在記憶體的假檔案(`io.BytesIO`),影響不大;但若是實際檔案,務必在處理完成後關閉檔案。 + +### 檔案與 Async { #files-and-async } + +多數情況下,類檔案物件預設不相容於 async/await。 + +例如,它們沒有 `await file.read()`,也不支援 `async for chunk in file`。 + +而且在許多情況下,讀取它們會是阻塞操作(可能阻塞事件迴圈),因為資料是從磁碟或網路讀取。 + +/// info + +上面的範例其實是例外,因為 `io.BytesIO` 物件已在記憶體中,讀取不會阻塞任何東西。 + +但在多數情況下,讀取檔案或類檔案物件會造成阻塞。 + +/// + +為了避免阻塞事件迴圈,你可以將路徑操作函式宣告為一般的 `def`(而非 `async def`),這樣 FastAPI 會在 threadpool worker 上執行它,避免阻塞主事件迴圈。 + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} + +/// tip + +如果你需要在 async 函式內呼叫阻塞程式碼,或在阻塞函式中呼叫 async 函式,你可以使用 [Asyncer](https://asyncer.tiangolo.com),它是 FastAPI 的姊妹函式庫。 + +/// + +### `yield from` { #yield-from } + +當你在迭代某個物件(如類檔案物件),並對每個項目使用 `yield` 時,也可以用 `yield from` 直接逐項產出,省略 `for` 迴圈。 + +這不是 FastAPI 特有的功能,而是 Python 語法;不過這招很實用。 😎 + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[37:40] hl[40] *} diff --git a/docs/zh-hant/docs/advanced/strict-content-type.md b/docs/zh-hant/docs/advanced/strict-content-type.md new file mode 100644 index 0000000000..9d2ffb8430 --- /dev/null +++ b/docs/zh-hant/docs/advanced/strict-content-type.md @@ -0,0 +1,88 @@ +# 嚴格的 Content-Type 檢查 { #strict-content-type-checking } + +預設情況下,FastAPI 會對 JSON 請求主體使用嚴格的 `Content-Type` 標頭檢查。也就是說,JSON 請求必須包含有效的 `Content-Type` 標頭(例如 `application/json`),請求主體(body)才能被解析為 JSON。 + +## CSRF 風險 { #csrf-risk } + +這個預設行為在某個非常特定的情境下,能對一類跨站請求偽造(CSRF, Cross-Site Request Forgery)攻擊提供保護。 + +這類攻擊利用了瀏覽器在以下情況下允許腳本發送請求而不進行任何 CORS 預檢(preflight)檢查的事實: + +- 沒有 `Content-Type` 標頭(例如以 `fetch()` 並使用 `Blob` 作為 body) +- 且沒有送出任何身分驗證憑證 + +這種攻擊主要與以下情境相關: + +- 應用在本機(例如 `localhost`)或內部網路中執行 +- 並且應用沒有任何身分驗證,假設同一個網路中的任何請求都可被信任 + +## 攻擊範例 { #example-attack } + +假設你打造了一個在本機執行 AI 代理(AI agent)的方法。 + +它提供一個 API: + +``` +http://localhost:8000/v1/agents/multivac +``` + +同時也有一個前端: + +``` +http://localhost:8000 +``` + +/// tip | 提示 + +請注意兩者的主機(host)相同。 + +/// + +接著你可以透過前端讓 AI 代理代你執行動作。 + +由於它在本機執行、而非公開的網際網路上,你決定不設定任何身分驗證,只信任對本機網路的存取。 + +然後你的某位使用者可能安裝並在本機執行它。 + +接著他可能打開一個惡意網站,例如: + +``` +https://evilhackers.example.com +``` + +該惡意網站會使用 `fetch()` 並以 `Blob` 作為 body,向本機的 API 發送請求: + +``` +http://localhost:8000/v1/agents/multivac +``` + +即使惡意網站與本機應用的主機不同,瀏覽器也不會觸發 CORS 預檢請求,因為: + +- 它在未經任何身分驗證的情況下執行,不需要送出任何憑證。 +- 由於缺少 `Content-Type` 標頭,瀏覽器認為它並未傳送 JSON。 + +接著,惡意網站就能讓本機的 AI 代理替使用者向前老闆發飆傳訊... 或做更糟的事。😅 + +## 公開的網際網路 { #open-internet } + +如果你的應用部署在公開的網際網路上,你不會「信任網路」而允許任何人在未經身分驗證的情況下發送具權限的請求。 + +攻擊者可以直接執行腳本向你的 API 發送請求,無需透過瀏覽器互動,因此你多半已經對任何具權限的端點做了防護。 + +在這種情況下,這種攻擊/風險不適用於你。 + +此風險與攻擊主要與應用只在本機或內部網路上執行,且「僅依賴此為保護」的情境相關。 + +## 允許沒有 Content-Type 的請求 { #allowing-requests-without-content-type } + +若你需要支援未送出 `Content-Type` 標頭的客戶端,可以將 `strict_content_type=False` 以停用嚴格檢查: + +{* ../../docs_src/strict_content_type/tutorial001_py310.py hl[4] *} + +啟用此設定後,缺少 `Content-Type` 標頭的請求會將其主體解析為 JSON,這與舊版 FastAPI 的行為相同。 + +/// info | 資訊 + +此行為與設定新增於 FastAPI 0.132.0。 + +/// diff --git a/docs/zh-hant/docs/editor-support.md b/docs/zh-hant/docs/editor-support.md new file mode 100644 index 0000000000..ff4d8f43db --- /dev/null +++ b/docs/zh-hant/docs/editor-support.md @@ -0,0 +1,23 @@ +# 編輯器支援 { #editor-support } + +官方的 [FastAPI 擴充套件](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) 透過支援路徑操作(path operation)探索、導覽,以及 FastAPI Cloud 部署與即時日誌串流,強化你的 FastAPI 開發流程。 + +想了解更多關於此擴充套件的細節,請參考其 [GitHub 儲存庫](https://github.com/fastapi/fastapi-vscode) 中的 README。 + +## 安裝與設定 { #setup-and-installation } + +**FastAPI 擴充套件** 同時提供給 [VS Code](https://code.visualstudio.com/) 與 [Cursor](https://www.cursor.com/)。你可以在各編輯器的擴充套件面板中直接安裝:搜尋「FastAPI」,並選擇由 **FastAPI Labs** 發佈的擴充套件。此擴充套件同樣可在瀏覽器版編輯器(如 [vscode.dev](https://vscode.dev) 與 [github.dev](https://github.dev))中使用。 + +### 應用程式探索 { #application-discovery } + +預設情況下,擴充套件會自動在你的工作區中,掃描會實例化 `FastAPI()` 的檔案,以發現 FastAPI 應用程式。若自動偵測無法因應你的專案結構,你可以在 `pyproject.toml` 的 `[tool.fastapi]` 中,或在 VS Code 設定的 `fastapi.entryPoint` 中,使用模組標記法(例如 `myapp.main:app`)指定入口點。 + +## 功能 { #features } + +- **Path Operation Explorer** - 顯示應用程式中所有 *路徑操作* 的側邊欄樹狀檢視。點擊即可跳至任一路由或 router 定義。 +- **Route Search** - 使用 Ctrl + Shift + E(macOS:Cmd + Shift + E)依路徑、方法或名稱進行搜尋。 +- **CodeLens Navigation** - 在測試用 client 呼叫(例如 `client.get('/items')`)上方提供可點連結,一鍵跳至對應的路徑操作,讓你在測試與實作間快速切換。 +- **Deploy to FastAPI Cloud** - 一鍵將你的應用程式部署到 [FastAPI Cloud](https://fastapicloud.com/)。 +- **Stream Application Logs** - 從部署於 FastAPI Cloud 的應用程式即時串流日誌,並支援層級篩選與文字搜尋。 + +若你想熟悉此擴充套件的功能,可開啟命令面板(Ctrl + Shift + P;macOS:Cmd + Shift + P),選擇 "Welcome: Open walkthrough...",然後挑選 "Get started with FastAPI" walkthrough。 diff --git a/docs/zh-hant/docs/tutorial/server-sent-events.md b/docs/zh-hant/docs/tutorial/server-sent-events.md new file mode 100644 index 0000000000..ced91e358a --- /dev/null +++ b/docs/zh-hant/docs/tutorial/server-sent-events.md @@ -0,0 +1,120 @@ +# Server-Sent Events(SSE) { #server-sent-events-sse } + +你可以使用 Server-Sent Events(SSE)把資料串流傳送給用戶端。 + +這與[串流 JSON Lines](stream-json-lines.md)類似,但使用瀏覽器原生支援、透過 [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) 的 `text/event-stream` 格式。 + +/// info + +在 FastAPI 0.135.0 新增。 + +/// + +## 什麼是 Server-Sent Events? { #what-are-server-sent-events } + +SSE 是一種透過 HTTP 從伺服器向用戶端串流傳送資料的標準。 + +每個事件都是一個小型文字區塊,包含 `data`、`event`、`id` 和 `retry` 等「欄位」,並以空白行分隔。 + +看起來像這樣: + +``` +data: {"name": "Portal Gun", "price": 999.99} + +data: {"name": "Plumbus", "price": 32.99} + +``` + +SSE 常用於 AI 聊天串流、即時通知、日誌與可觀察性,以及其他由伺服器主動推送更新給用戶端的情境。 + +/// tip + +如果你要串流二進位資料,例如影片或音訊,請參考進階指南:[串流資料](../advanced/stream-data.md)。 + +/// + +## 使用 FastAPI 串流 SSE { #stream-sse-with-fastapi } + +要在 FastAPI 中串流 SSE,請在你的路徑操作函式(path operation function)中使用 `yield`,並設定 `response_class=EventSourceResponse`。 + +從 `fastapi.sse` 匯入 `EventSourceResponse`: + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[4,22] *} + +每個 `yield` 的項目都會以 JSON 編碼並放在 SSE 事件的 `data:` 欄位中送出。 + +如果你把回傳型別宣告為 `AsyncIterable[Item]`,FastAPI 會用它來透過 Pydantic 進行**驗證**、**文件化**與**序列化**。 + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[10:12,23] *} + +/// tip + +因為 Pydantic 會在 **Rust** 端進行序列化,如果你有宣告回傳型別,效能會比未宣告時高很多。 + +/// + +### 非 async 的路徑操作函式 { #non-async-path-operation-functions } + +你也可以使用一般的 `def` 函式(沒有 `async`),並同樣使用 `yield`。 + +FastAPI 會確保正確執行,不會阻塞事件迴圈。 + +由於此函式不是 async,正確的回傳型別是 `Iterable[Item]`: + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[28:31] hl[29] *} + +### 無回傳型別 { #no-return-type } + +你也可以省略回傳型別。FastAPI 會使用 [`jsonable_encoder`](./encoder.md) 轉換資料並送出。 + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[34:37] hl[35] *} + +## `ServerSentEvent` { #serversentevent } + +如果你需要設定 `event`、`id`、`retry` 或 `comment` 等 SSE 欄位,你可以改為 `yield` 出 `ServerSentEvent` 物件,而不是單純的資料。 + +從 `fastapi.sse` 匯入 `ServerSentEvent`: + +{* ../../docs_src/server_sent_events/tutorial002_py310.py hl[4,26] *} + +`data` 欄位一律會以 JSON 編碼。你可以傳入任何可序列化為 JSON 的值,包括 Pydantic 模型。 + +## 原始資料 { #raw-data } + +如果你需要在**不**進行 JSON 編碼的情況下傳送資料,請使用 `raw_data` 取代 `data`。 + +這對於傳送已格式化的文字、日誌行或特殊的 "哨兵" 值(例如 `[DONE]`)很有用。 + +{* ../../docs_src/server_sent_events/tutorial003_py310.py hl[17] *} + +/// note + +`data` 與 `raw_data` 互斥。每個 `ServerSentEvent` 只能設定其中一個。 + +/// + +## 使用 `Last-Event-ID` 繼續 { #resuming-with-last-event-id } + +當瀏覽器在連線中斷後重新連線時,會在 `Last-Event-ID` 標頭中傳送最後接收到的 `id`。 + +你可以將它作為標頭參數讀取,並用來從用戶端中斷處繼續串流: + +{* ../../docs_src/server_sent_events/tutorial004_py310.py hl[25,27,31] *} + +## 使用 POST 的 SSE { #sse-with-post } + +SSE 可搭配**任何 HTTP 方法**,不僅限於 `GET`。 + +這對於像是透過 `POST` 串流 SSE 的協定(例如 [MCP](https://modelcontextprotocol.io))很有用: + +{* ../../docs_src/server_sent_events/tutorial005_py310.py hl[14] *} + +## 技術細節 { #technical-details } + +FastAPI 內建實作了一些 SSE 的最佳實務。 + +- 當 15 秒內沒有任何訊息時,傳送一次**「保活」`ping` 註解**,以避免某些代理伺服器關閉連線;此作法源自於[HTML 規範:Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes)中的建議。 +- 設定 `Cache-Control: no-cache` 標頭,以**防止快取**串流內容。 +- 設定特殊標頭 `X-Accel-Buffering: no`,以**避免**在像 Nginx 這類代理中被**緩衝**。 + +你不需要做任何事,開箱即用。🤓 diff --git a/docs/zh-hant/docs/tutorial/stream-json-lines.md b/docs/zh-hant/docs/tutorial/stream-json-lines.md new file mode 100644 index 0000000000..204d32ffd3 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/stream-json-lines.md @@ -0,0 +1,111 @@ +# 串流 JSON Lines { #stream-json-lines } + +當你有一連串資料想以「**串流**」方式傳送時,可以使用 **JSON Lines**。 + +/// info + +在 FastAPI 0.134.0 新增。 + +/// + +## 什麼是串流? { #what-is-a-stream } + +「**Streaming**」資料表示你的應用會在整個資料序列尚未完全準備好之前,就開始將資料項目傳送給用戶端。 + +也就是說,它會先送出第一個項目,用戶端接收並開始處理時,你的應用可能仍在產生下一個項目。 + +```mermaid +sequenceDiagram + participant App + participant Client + + App->>App: Produce Item 1 + App->>Client: Send Item 1 + App->>App: Produce Item 2 + Client->>Client: Process Item 1 + App->>Client: Send Item 2 + App->>App: Produce Item 3 + Client->>Client: Process Item 2 + App->>Client: Send Item 3 + Client->>Client: Process Item 3 + Note over App: Keeps producing... + Note over Client: Keeps consuming... +``` + +它甚至可以是無限串流,你可以一直持續傳送資料。 + +## JSON Lines { #json-lines } + +在這些情況下,常見做法是傳送「**JSON Lines**」,這是一種每一行各包含一個 JSON 物件的格式。 + +回應的 content type 會是 `application/jsonl`(而不是 `application/json`),而本體內容會像這樣: + +```json +{"name": "Plumbus", "description": "A multi-purpose household device."} +{"name": "Portal Gun", "description": "A portal opening device."} +{"name": "Meeseeks Box", "description": "A box that summons a Meeseeks."} +``` + +它和 JSON 陣列(相當於 Python 的 list)很像,但不同於用 `[]` 包起來並以 `,` 分隔項目,它是每一行各放一個 JSON 物件,彼此以換行字元分隔。 + +/// info + +重點在於你的應用能夠逐行產生資料,同時用戶端在消耗前一行的資料。 + +/// + +/// note | 技術細節 + +由於每個 JSON 物件會以換行分隔,它們的內容中不能包含實際的換行字元,但可以包含跳脫後的換行(`\n`),這是 JSON 標準的一部分。 + +不過通常你不需要為此煩惱,這些都會自動處理,繼續往下看吧。🤓 + +/// + +## 使用情境 { #use-cases } + +你可以用這種方式從 **AI LLM** 服務、**日誌**或**遙測**串流資料,或任何能以 **JSON** 項目結構化的其他型態資料。 + +/// tip + +如果你想串流二進位資料,例如影像或音訊,請參考進階指南:[串流資料](../advanced/stream-data.md)。 + +/// + +## 使用 FastAPI 串流 JSON Lines { #stream-json-lines-with-fastapi } + +要用 FastAPI 串流 JSON Lines,你可以在你的*路徑操作函式*中改用 `yield` 逐一產生項目,而不是用 `return`。 + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[24] *} + +如果你要回傳的每個 JSON 項目型別都是 `Item`(一個 Pydantic 模型),而且該函式是 async,你可以將回傳型別宣告為 `AsyncIterable[Item]`: + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[9:11,22] *} + +如果你宣告了回傳型別,FastAPI 會用它來進行資料的**驗證**、在 OpenAPI 中**文件化**、**過濾**,並使用 Pydantic 進行**序列化**。 + +/// tip + +由於 Pydantic 會在 **Rust** 端進行序列化,宣告回傳型別可獲得比未宣告時高得多的**效能**。 + +/// + +### 非 async 的*路徑操作函式* { #non-async-path-operation-functions } + +你也可以用一般的 `def` 函式(沒有 `async`),同樣用 `yield`。 + +FastAPI 會確保正確執行,不會阻塞事件迴圈。 + +因為這種情況下函式不是 async,正確的回傳型別會是 `Iterable[Item]`: + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[27:30] hl[28] *} + +### 不宣告回傳型別 { #no-return-type } + +你也可以省略回傳型別。此時 FastAPI 會使用 [`jsonable_encoder`](./encoder.md) 將資料轉換為可序列化為 JSON 的形式,然後以 JSON Lines 傳送。 + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[33:36] hl[34] *} + +## 伺服器推播事件(SSE) { #server-sent-events-sse } + +FastAPI 也原生支援 Server-Sent Events(SSE),它們與此相當類似,但多了幾個細節。你可以在下一章學到更多:[伺服器推播事件(SSE)](server-sent-events.md)。🤓 From 6cd1a2c75dd9fe539326377d45dd2e8baf5a4757 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Mar 2026 14:33:32 +0000 Subject: [PATCH 08/69] =?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 812a108c9e..a0c527b984 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Translations +* 🌐 Update translations for zh-hant (add-missing). PR [#15176](https://github.com/fastapi/fastapi/pull/15176) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (add-missing). PR [#15175](https://github.com/fastapi/fastapi/pull/15175) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ja (update-outdated). PR [#15171](https://github.com/fastapi/fastapi/pull/15171) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (update-outdated). PR [#15170](https://github.com/fastapi/fastapi/pull/15170) by [@tiangolo](https://github.com/tiangolo). From 2fba244c3a6f8c85d289f604d22b74467fce5424 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 15:59:48 +0100 Subject: [PATCH 09/69] =?UTF-8?q?=E2=AC=86=20Bump=20ujson=20from=205.11.0?= =?UTF-8?q?=20to=205.12.0=20(#15150)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 160 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 84 insertions(+), 76 deletions(-) diff --git a/uv.lock b/uv.lock index 9a10d7bda6..4c16fe10a9 100644 --- a/uv.lock +++ b/uv.lock @@ -479,6 +479,9 @@ dependencies = [ { name = "tinycss2" }, ] sdist = { url = "https://files.pythonhosted.org/packages/38/07/e8412a13019b3f737972dea23a2c61ca42becafc16c9338f4ca7a0caa993/cairosvg-2.9.0.tar.gz", hash = "sha256:1debb00cd2da11350d8b6f5ceb739f1b539196d71d5cf5eb7363dbd1bfbc8dc5", size = 40877, upload-time = "2026-03-13T15:42:00.564Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/e0/5011747466414c12cac8a8df77aa235068669a6a5a5df301a96209db6054/cairosvg-2.9.0-py3-none-any.whl", hash = "sha256:4b82d07d145377dffdfc19d9791bd5fb65539bb4da0adecf0bdbd9cd4ffd7c68", size = 45962, upload-time = "2026-03-14T13:56:33.512Z" }, +] [[package]] name = "certifi" @@ -5769,82 +5772,87 @@ wheels = [ [[package]] name = "ujson" -version = "5.11.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/d9/3f17e3c5773fb4941c68d9a37a47b1a79c9649d6c56aefbed87cc409d18a/ujson-5.11.0.tar.gz", hash = "sha256:e204ae6f909f099ba6b6b942131cee359ddda2b6e4ea39c12eb8b991fe2010e0", size = 7156583, upload-time = "2025-08-20T11:57:02.452Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/86/0c/8bf7a4fabfd01c7eed92d9b290930ce6d14910dec708e73538baa38885d1/ujson-5.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:446e8c11c06048611c9d29ef1237065de0af07cabdd97e6b5b527b957692ec25", size = 55248, upload-time = "2025-08-20T11:55:02.368Z" }, - { url = "https://files.pythonhosted.org/packages/7b/2e/eeab0b8b641817031ede4f790db4c4942df44a12f44d72b3954f39c6a115/ujson-5.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:16ccb973b7ada0455201808ff11d48fe9c3f034a6ab5bd93b944443c88299f89", size = 53157, upload-time = "2025-08-20T11:55:04.012Z" }, - { url = "https://files.pythonhosted.org/packages/21/1b/a4e7a41870797633423ea79618526747353fd7be9191f3acfbdee0bf264b/ujson-5.11.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3134b783ab314d2298d58cda7e47e7a0f7f71fc6ade6ac86d5dbeaf4b9770fa6", size = 57657, upload-time = "2025-08-20T11:55:05.169Z" }, - { url = "https://files.pythonhosted.org/packages/94/ae/4e0d91b8f6db7c9b76423b3649612189506d5a06ddd3b6334b6d37f77a01/ujson-5.11.0-cp310-cp310-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:185f93ebccffebc8baf8302c869fac70dd5dd78694f3b875d03a31b03b062cdb", size = 59780, upload-time = "2025-08-20T11:55:06.325Z" }, - { url = "https://files.pythonhosted.org/packages/b3/cc/46b124c2697ca2da7c65c4931ed3cb670646978157aa57a7a60f741c530f/ujson-5.11.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d06e87eded62ff0e5f5178c916337d2262fdbc03b31688142a3433eabb6511db", size = 57307, upload-time = "2025-08-20T11:55:07.493Z" }, - { url = "https://files.pythonhosted.org/packages/39/eb/20dd1282bc85dede2f1c62c45b4040bc4c389c80a05983515ab99771bca7/ujson-5.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:181fb5b15703a8b9370b25345d2a1fd1359f0f18776b3643d24e13ed9c036d4c", size = 1036369, upload-time = "2025-08-20T11:55:09.192Z" }, - { url = "https://files.pythonhosted.org/packages/64/a2/80072439065d493e3a4b1fbeec991724419a1b4c232e2d1147d257cac193/ujson-5.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a4df61a6df0a4a8eb5b9b1ffd673429811f50b235539dac586bb7e9e91994138", size = 1195738, upload-time = "2025-08-20T11:55:11.402Z" }, - { url = "https://files.pythonhosted.org/packages/5d/7e/d77f9e9c039d58299c350c978e086a804d1fceae4fd4a1cc6e8d0133f838/ujson-5.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6eff24e1abd79e0ec6d7eae651dd675ddbc41f9e43e29ef81e16b421da896915", size = 1088718, upload-time = "2025-08-20T11:55:13.297Z" }, - { url = "https://files.pythonhosted.org/packages/ab/f1/697559d45acc849cada6b3571d53522951b1a64027400507aabc6a710178/ujson-5.11.0-cp310-cp310-win32.whl", hash = "sha256:30f607c70091483550fbd669a0b37471e5165b317d6c16e75dba2aa967608723", size = 39653, upload-time = "2025-08-20T11:55:14.869Z" }, - { url = "https://files.pythonhosted.org/packages/86/a2/70b73a0f55abe0e6b8046d365d74230c20c5691373e6902a599b2dc79ba1/ujson-5.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:3d2720e9785f84312b8e2cb0c2b87f1a0b1c53aaab3b2af3ab817d54409012e0", size = 43720, upload-time = "2025-08-20T11:55:15.897Z" }, - { url = "https://files.pythonhosted.org/packages/1c/5f/b19104afa455630b43efcad3a24495b9c635d92aa8f2da4f30e375deb1a2/ujson-5.11.0-cp310-cp310-win_arm64.whl", hash = "sha256:85e6796631165f719084a9af00c79195d3ebf108151452fefdcb1c8bb50f0105", size = 38410, upload-time = "2025-08-20T11:55:17.556Z" }, - { url = "https://files.pythonhosted.org/packages/da/ea/80346b826349d60ca4d612a47cdf3533694e49b45e9d1c07071bb867a184/ujson-5.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d7c46cb0fe5e7056b9acb748a4c35aa1b428025853032540bb7e41f46767321f", size = 55248, upload-time = "2025-08-20T11:55:19.033Z" }, - { url = "https://files.pythonhosted.org/packages/57/df/b53e747562c89515e18156513cc7c8ced2e5e3fd6c654acaa8752ffd7cd9/ujson-5.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8951bb7a505ab2a700e26f691bdfacf395bc7e3111e3416d325b513eea03a58", size = 53156, upload-time = "2025-08-20T11:55:20.174Z" }, - { url = "https://files.pythonhosted.org/packages/41/b8/ab67ec8c01b8a3721fd13e5cb9d85ab2a6066a3a5e9148d661a6870d6293/ujson-5.11.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:952c0be400229940248c0f5356514123d428cba1946af6fa2bbd7503395fef26", size = 57657, upload-time = "2025-08-20T11:55:21.296Z" }, - { url = "https://files.pythonhosted.org/packages/7b/c7/fb84f27cd80a2c7e2d3c6012367aecade0da936790429801803fa8d4bffc/ujson-5.11.0-cp311-cp311-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:94fcae844f1e302f6f8095c5d1c45a2f0bfb928cccf9f1b99e3ace634b980a2a", size = 59779, upload-time = "2025-08-20T11:55:22.772Z" }, - { url = "https://files.pythonhosted.org/packages/5d/7c/48706f7c1e917ecb97ddcfb7b1d756040b86ed38290e28579d63bd3fcc48/ujson-5.11.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e0ec1646db172beb8d3df4c32a9d78015e671d2000af548252769e33079d9a6", size = 57284, upload-time = "2025-08-20T11:55:24.01Z" }, - { url = "https://files.pythonhosted.org/packages/ec/ce/48877c6eb4afddfd6bd1db6be34456538c07ca2d6ed233d3f6c6efc2efe8/ujson-5.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:da473b23e3a54448b008d33f742bcd6d5fb2a897e42d1fc6e7bf306ea5d18b1b", size = 1036395, upload-time = "2025-08-20T11:55:25.725Z" }, - { url = "https://files.pythonhosted.org/packages/8b/7a/2c20dc97ad70cd7c31ad0596ba8e2cf8794d77191ba4d1e0bded69865477/ujson-5.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:aa6b3d4f1c0d3f82930f4cbd7fe46d905a4a9205a7c13279789c1263faf06dba", size = 1195731, upload-time = "2025-08-20T11:55:27.915Z" }, - { url = "https://files.pythonhosted.org/packages/15/f5/ca454f2f6a2c840394b6f162fff2801450803f4ff56c7af8ce37640b8a2a/ujson-5.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4843f3ab4fe1cc596bb7e02228ef4c25d35b4bb0809d6a260852a4bfcab37ba3", size = 1088710, upload-time = "2025-08-20T11:55:29.426Z" }, - { url = "https://files.pythonhosted.org/packages/fe/d3/9ba310e07969bc9906eb7548731e33a0f448b122ad9705fed699c9b29345/ujson-5.11.0-cp311-cp311-win32.whl", hash = "sha256:e979fbc469a7f77f04ec2f4e853ba00c441bf2b06720aa259f0f720561335e34", size = 39648, upload-time = "2025-08-20T11:55:31.194Z" }, - { url = "https://files.pythonhosted.org/packages/57/f7/da05b4a8819f1360be9e71fb20182f0bb3ec611a36c3f213f4d20709e099/ujson-5.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:683f57f0dd3acdd7d9aff1de0528d603aafcb0e6d126e3dc7ce8b020a28f5d01", size = 43717, upload-time = "2025-08-20T11:55:32.241Z" }, - { url = "https://files.pythonhosted.org/packages/9a/cc/f3f9ac0f24f00a623a48d97dc3814df5c2dc368cfb00031aa4141527a24b/ujson-5.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:7855ccea3f8dad5e66d8445d754fc1cf80265a4272b5f8059ebc7ec29b8d0835", size = 38402, upload-time = "2025-08-20T11:55:33.641Z" }, - { url = "https://files.pythonhosted.org/packages/b9/ef/a9cb1fce38f699123ff012161599fb9f2ff3f8d482b4b18c43a2dc35073f/ujson-5.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7895f0d2d53bd6aea11743bd56e3cb82d729980636cd0ed9b89418bf66591702", size = 55434, upload-time = "2025-08-20T11:55:34.987Z" }, - { url = "https://files.pythonhosted.org/packages/b1/05/dba51a00eb30bd947791b173766cbed3492269c150a7771d2750000c965f/ujson-5.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12b5e7e22a1fe01058000d1b317d3b65cc3daf61bd2ea7a2b76721fe160fa74d", size = 53190, upload-time = "2025-08-20T11:55:36.384Z" }, - { url = "https://files.pythonhosted.org/packages/03/3c/fd11a224f73fbffa299fb9644e425f38b38b30231f7923a088dd513aabb4/ujson-5.11.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0180a480a7d099082501cad1fe85252e4d4bf926b40960fb3d9e87a3a6fbbc80", size = 57600, upload-time = "2025-08-20T11:55:37.692Z" }, - { url = "https://files.pythonhosted.org/packages/55/b9/405103cae24899df688a3431c776e00528bd4799e7d68820e7ebcf824f92/ujson-5.11.0-cp312-cp312-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:fa79fdb47701942c2132a9dd2297a1a85941d966d8c87bfd9e29b0cf423f26cc", size = 59791, upload-time = "2025-08-20T11:55:38.877Z" }, - { url = "https://files.pythonhosted.org/packages/17/7b/2dcbc2bbfdbf68f2368fb21ab0f6735e872290bb604c75f6e06b81edcb3f/ujson-5.11.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8254e858437c00f17cb72e7a644fc42dad0ebb21ea981b71df6e84b1072aaa7c", size = 57356, upload-time = "2025-08-20T11:55:40.036Z" }, - { url = "https://files.pythonhosted.org/packages/d1/71/fea2ca18986a366c750767b694430d5ded6b20b6985fddca72f74af38a4c/ujson-5.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1aa8a2ab482f09f6c10fba37112af5f957689a79ea598399c85009f2f29898b5", size = 1036313, upload-time = "2025-08-20T11:55:41.408Z" }, - { url = "https://files.pythonhosted.org/packages/a3/bb/d4220bd7532eac6288d8115db51710fa2d7d271250797b0bfba9f1e755af/ujson-5.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a638425d3c6eed0318df663df44480f4a40dc87cc7c6da44d221418312f6413b", size = 1195782, upload-time = "2025-08-20T11:55:43.357Z" }, - { url = "https://files.pythonhosted.org/packages/80/47/226e540aa38878ce1194454385701d82df538ccb5ff8db2cf1641dde849a/ujson-5.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7e3cff632c1d78023b15f7e3a81c3745cd3f94c044d1e8fa8efbd6b161997bbc", size = 1088817, upload-time = "2025-08-20T11:55:45.262Z" }, - { url = "https://files.pythonhosted.org/packages/7e/81/546042f0b23c9040d61d46ea5ca76f0cc5e0d399180ddfb2ae976ebff5b5/ujson-5.11.0-cp312-cp312-win32.whl", hash = "sha256:be6b0eaf92cae8cdee4d4c9e074bde43ef1c590ed5ba037ea26c9632fb479c88", size = 39757, upload-time = "2025-08-20T11:55:46.522Z" }, - { url = "https://files.pythonhosted.org/packages/44/1b/27c05dc8c9728f44875d74b5bfa948ce91f6c33349232619279f35c6e817/ujson-5.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:b7b136cc6abc7619124fd897ef75f8e63105298b5ca9bdf43ebd0e1fa0ee105f", size = 43859, upload-time = "2025-08-20T11:55:47.987Z" }, - { url = "https://files.pythonhosted.org/packages/22/2d/37b6557c97c3409c202c838aa9c960ca3896843b4295c4b7bb2bbd260664/ujson-5.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:6cd2df62f24c506a0ba322d5e4fe4466d47a9467b57e881ee15a31f7ecf68ff6", size = 38361, upload-time = "2025-08-20T11:55:49.122Z" }, - { url = "https://files.pythonhosted.org/packages/1c/ec/2de9dd371d52c377abc05d2b725645326c4562fc87296a8907c7bcdf2db7/ujson-5.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:109f59885041b14ee9569bf0bb3f98579c3fa0652317b355669939e5fc5ede53", size = 55435, upload-time = "2025-08-20T11:55:50.243Z" }, - { url = "https://files.pythonhosted.org/packages/5b/a4/f611f816eac3a581d8a4372f6967c3ed41eddbae4008d1d77f223f1a4e0a/ujson-5.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a31c6b8004438e8c20fc55ac1c0e07dad42941db24176fe9acf2815971f8e752", size = 53193, upload-time = "2025-08-20T11:55:51.373Z" }, - { url = "https://files.pythonhosted.org/packages/e9/c5/c161940967184de96f5cbbbcce45b562a4bf851d60f4c677704b1770136d/ujson-5.11.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78c684fb21255b9b90320ba7e199780f653e03f6c2528663768965f4126a5b50", size = 57603, upload-time = "2025-08-20T11:55:52.583Z" }, - { url = "https://files.pythonhosted.org/packages/2b/d6/c7b2444238f5b2e2d0e3dab300b9ddc3606e4b1f0e4bed5a48157cebc792/ujson-5.11.0-cp313-cp313-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:4c9f5d6a27d035dd90a146f7761c2272cf7103de5127c9ab9c4cd39ea61e878a", size = 59794, upload-time = "2025-08-20T11:55:53.69Z" }, - { url = "https://files.pythonhosted.org/packages/fe/a3/292551f936d3d02d9af148f53e1bc04306b00a7cf1fcbb86fa0d1c887242/ujson-5.11.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:837da4d27fed5fdc1b630bd18f519744b23a0b5ada1bbde1a36ba463f2900c03", size = 57363, upload-time = "2025-08-20T11:55:54.843Z" }, - { url = "https://files.pythonhosted.org/packages/90/a6/82cfa70448831b1a9e73f882225980b5c689bf539ec6400b31656a60ea46/ujson-5.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:787aff4a84da301b7f3bac09bc696e2e5670df829c6f8ecf39916b4e7e24e701", size = 1036311, upload-time = "2025-08-20T11:55:56.197Z" }, - { url = "https://files.pythonhosted.org/packages/84/5c/96e2266be50f21e9b27acaee8ca8f23ea0b85cb998c33d4f53147687839b/ujson-5.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6dd703c3e86dc6f7044c5ac0b3ae079ed96bf297974598116aa5fb7f655c3a60", size = 1195783, upload-time = "2025-08-20T11:55:58.081Z" }, - { url = "https://files.pythonhosted.org/packages/8d/20/78abe3d808cf3bb3e76f71fca46cd208317bf461c905d79f0d26b9df20f1/ujson-5.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3772e4fe6b0c1e025ba3c50841a0ca4786825a4894c8411bf8d3afe3a8061328", size = 1088822, upload-time = "2025-08-20T11:55:59.469Z" }, - { url = "https://files.pythonhosted.org/packages/d8/50/8856e24bec5e2fc7f775d867aeb7a3f137359356200ac44658f1f2c834b2/ujson-5.11.0-cp313-cp313-win32.whl", hash = "sha256:8fa2af7c1459204b7a42e98263b069bd535ea0cd978b4d6982f35af5a04a4241", size = 39753, upload-time = "2025-08-20T11:56:01.345Z" }, - { url = "https://files.pythonhosted.org/packages/5b/d8/1baee0f4179a4d0f5ce086832147b6cc9b7731c24ca08e14a3fdb8d39c32/ujson-5.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:34032aeca4510a7c7102bd5933f59a37f63891f30a0706fb46487ab6f0edf8f0", size = 43866, upload-time = "2025-08-20T11:56:02.552Z" }, - { url = "https://files.pythonhosted.org/packages/a9/8c/6d85ef5be82c6d66adced3ec5ef23353ed710a11f70b0b6a836878396334/ujson-5.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:ce076f2df2e1aa62b685086fbad67f2b1d3048369664b4cdccc50707325401f9", size = 38363, upload-time = "2025-08-20T11:56:03.688Z" }, - { url = "https://files.pythonhosted.org/packages/28/08/4518146f4984d112764b1dfa6fb7bad691c44a401adadaa5e23ccd930053/ujson-5.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:65724738c73645db88f70ba1f2e6fb678f913281804d5da2fd02c8c5839af302", size = 55462, upload-time = "2025-08-20T11:56:04.873Z" }, - { url = "https://files.pythonhosted.org/packages/29/37/2107b9a62168867a692654d8766b81bd2fd1e1ba13e2ec90555861e02b0c/ujson-5.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:29113c003ca33ab71b1b480bde952fbab2a0b6b03a4ee4c3d71687cdcbd1a29d", size = 53246, upload-time = "2025-08-20T11:56:06.054Z" }, - { url = "https://files.pythonhosted.org/packages/9b/f8/25583c70f83788edbe3ca62ce6c1b79eff465d78dec5eb2b2b56b3e98b33/ujson-5.11.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c44c703842024d796b4c78542a6fcd5c3cb948b9fc2a73ee65b9c86a22ee3638", size = 57631, upload-time = "2025-08-20T11:56:07.374Z" }, - { url = "https://files.pythonhosted.org/packages/ed/ca/19b3a632933a09d696f10dc1b0dfa1d692e65ad507d12340116ce4f67967/ujson-5.11.0-cp314-cp314-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:e750c436fb90edf85585f5c62a35b35082502383840962c6983403d1bd96a02c", size = 59877, upload-time = "2025-08-20T11:56:08.534Z" }, - { url = "https://files.pythonhosted.org/packages/55/7a/4572af5324ad4b2bfdd2321e898a527050290147b4ea337a79a0e4e87ec7/ujson-5.11.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f278b31a7c52eb0947b2db55a5133fbc46b6f0ef49972cd1a80843b72e135aba", size = 57363, upload-time = "2025-08-20T11:56:09.758Z" }, - { url = "https://files.pythonhosted.org/packages/7b/71/a2b8c19cf4e1efe53cf439cdf7198ac60ae15471d2f1040b490c1f0f831f/ujson-5.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ab2cb8351d976e788669c8281465d44d4e94413718af497b4e7342d7b2f78018", size = 1036394, upload-time = "2025-08-20T11:56:11.168Z" }, - { url = "https://files.pythonhosted.org/packages/7a/3e/7b98668cba3bb3735929c31b999b374ebc02c19dfa98dfebaeeb5c8597ca/ujson-5.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:090b4d11b380ae25453100b722d0609d5051ffe98f80ec52853ccf8249dfd840", size = 1195837, upload-time = "2025-08-20T11:56:12.6Z" }, - { url = "https://files.pythonhosted.org/packages/a1/ea/8870f208c20b43571a5c409ebb2fe9b9dba5f494e9e60f9314ac01ea8f78/ujson-5.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:80017e870d882d5517d28995b62e4e518a894f932f1e242cbc802a2fd64d365c", size = 1088837, upload-time = "2025-08-20T11:56:14.15Z" }, - { url = "https://files.pythonhosted.org/packages/63/b6/c0e6607e37fa47929920a685a968c6b990a802dec65e9c5181e97845985d/ujson-5.11.0-cp314-cp314-win32.whl", hash = "sha256:1d663b96eb34c93392e9caae19c099ec4133ba21654b081956613327f0e973ac", size = 41022, upload-time = "2025-08-20T11:56:15.509Z" }, - { url = "https://files.pythonhosted.org/packages/4e/56/f4fe86b4c9000affd63e9219e59b222dc48b01c534533093e798bf617a7e/ujson-5.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:849e65b696f0d242833f1df4182096cedc50d414215d1371fca85c541fbff629", size = 45111, upload-time = "2025-08-20T11:56:16.597Z" }, - { url = "https://files.pythonhosted.org/packages/0a/f3/669437f0280308db4783b12a6d88c00730b394327d8334cc7a32ef218e64/ujson-5.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:e73df8648c9470af2b6a6bf5250d4744ad2cf3d774dcf8c6e31f018bdd04d764", size = 39682, upload-time = "2025-08-20T11:56:17.763Z" }, - { url = "https://files.pythonhosted.org/packages/6e/cd/e9809b064a89fe5c4184649adeb13c1b98652db3f8518980b04227358574/ujson-5.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:de6e88f62796372fba1de973c11138f197d3e0e1d80bcb2b8aae1e826096d433", size = 55759, upload-time = "2025-08-20T11:56:18.882Z" }, - { url = "https://files.pythonhosted.org/packages/1b/be/ae26a6321179ebbb3a2e2685b9007c71bcda41ad7a77bbbe164005e956fc/ujson-5.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:49e56ef8066f11b80d620985ae36869a3ff7e4b74c3b6129182ec5d1df0255f3", size = 53634, upload-time = "2025-08-20T11:56:20.012Z" }, - { url = "https://files.pythonhosted.org/packages/ae/e9/fb4a220ee6939db099f4cfeeae796ecb91e7584ad4d445d4ca7f994a9135/ujson-5.11.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1a325fd2c3a056cf6c8e023f74a0c478dd282a93141356ae7f16d5309f5ff823", size = 58547, upload-time = "2025-08-20T11:56:21.175Z" }, - { url = "https://files.pythonhosted.org/packages/bd/f8/fc4b952b8f5fea09ea3397a0bd0ad019e474b204cabcb947cead5d4d1ffc/ujson-5.11.0-cp314-cp314t-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:a0af6574fc1d9d53f4ff371f58c96673e6d988ed2b5bf666a6143c782fa007e9", size = 60489, upload-time = "2025-08-20T11:56:22.342Z" }, - { url = "https://files.pythonhosted.org/packages/2e/e5/af5491dfda4f8b77e24cf3da68ee0d1552f99a13e5c622f4cef1380925c3/ujson-5.11.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:10f29e71ecf4ecd93a6610bd8efa8e7b6467454a363c3d6416db65de883eb076", size = 58035, upload-time = "2025-08-20T11:56:23.92Z" }, - { url = "https://files.pythonhosted.org/packages/c4/09/0945349dd41f25cc8c38d78ace49f14c5052c5bbb7257d2f466fa7bdb533/ujson-5.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1a0a9b76a89827a592656fe12e000cf4f12da9692f51a841a4a07aa4c7ecc41c", size = 1037212, upload-time = "2025-08-20T11:56:25.274Z" }, - { url = "https://files.pythonhosted.org/packages/49/44/8e04496acb3d5a1cbee3a54828d9652f67a37523efa3d3b18a347339680a/ujson-5.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b16930f6a0753cdc7d637b33b4e8f10d5e351e1fb83872ba6375f1e87be39746", size = 1196500, upload-time = "2025-08-20T11:56:27.517Z" }, - { url = "https://files.pythonhosted.org/packages/64/ae/4bc825860d679a0f208a19af2f39206dfd804ace2403330fdc3170334a2f/ujson-5.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:04c41afc195fd477a59db3a84d5b83a871bd648ef371cf8c6f43072d89144eef", size = 1089487, upload-time = "2025-08-20T11:56:29.07Z" }, - { url = "https://files.pythonhosted.org/packages/30/ed/5a057199fb0a5deabe0957073a1c1c1c02a3e99476cd03daee98ea21fa57/ujson-5.11.0-cp314-cp314t-win32.whl", hash = "sha256:aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5", size = 41859, upload-time = "2025-08-20T11:56:30.495Z" }, - { url = "https://files.pythonhosted.org/packages/aa/03/b19c6176bdf1dc13ed84b886e99677a52764861b6cc023d5e7b6ebda249d/ujson-5.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec", size = 46183, upload-time = "2025-08-20T11:56:31.574Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ca/a0413a3874b2dc1708b8796ca895bf363292f9c70b2e8ca482b7dbc0259d/ujson-5.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab", size = 40264, upload-time = "2025-08-20T11:56:32.773Z" }, - { url = "https://files.pythonhosted.org/packages/50/17/30275aa2933430d8c0c4ead951cc4fdb922f575a349aa0b48a6f35449e97/ujson-5.11.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:abae0fb58cc820092a0e9e8ba0051ac4583958495bfa5262a12f628249e3b362", size = 51206, upload-time = "2025-08-20T11:56:48.797Z" }, - { url = "https://files.pythonhosted.org/packages/c3/15/42b3924258eac2551f8f33fa4e35da20a06a53857ccf3d4deb5e5d7c0b6c/ujson-5.11.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fac6c0649d6b7c3682a0a6e18d3de6857977378dce8d419f57a0b20e3d775b39", size = 48907, upload-time = "2025-08-20T11:56:50.136Z" }, - { url = "https://files.pythonhosted.org/packages/94/7e/0519ff7955aba581d1fe1fb1ca0e452471250455d182f686db5ac9e46119/ujson-5.11.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b42c115c7c6012506e8168315150d1e3f76e7ba0f4f95616f4ee599a1372bbc", size = 50319, upload-time = "2025-08-20T11:56:51.63Z" }, - { url = "https://files.pythonhosted.org/packages/74/cf/209d90506b7d6c5873f82c5a226d7aad1a1da153364e9ebf61eff0740c33/ujson-5.11.0-pp311-pypy311_pp73-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:86baf341d90b566d61a394869ce77188cc8668f76d7bb2c311d77a00f4bdf844", size = 56584, upload-time = "2025-08-20T11:56:52.89Z" }, - { url = "https://files.pythonhosted.org/packages/e9/97/bd939bb76943cb0e1d2b692d7e68629f51c711ef60425fa5bb6968037ecd/ujson-5.11.0-pp311-pypy311_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4598bf3965fc1a936bd84034312bcbe00ba87880ef1ee33e33c1e88f2c398b49", size = 51588, upload-time = "2025-08-20T11:56:54.054Z" }, - { url = "https://files.pythonhosted.org/packages/52/5b/8c5e33228f7f83f05719964db59f3f9f276d272dc43752fa3bbf0df53e7b/ujson-5.11.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:416389ec19ef5f2013592f791486bef712ebce0cd59299bf9df1ba40bb2f6e04", size = 43835, upload-time = "2025-08-20T11:56:55.237Z" }, +version = "5.12.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cb/3e/c35530c5ffc25b71c59ae0cd7b8f99df37313daa162ce1e2f7925f7c2877/ujson-5.12.0.tar.gz", hash = "sha256:14b2e1eb528d77bc0f4c5bd1a7ebc05e02b5b41beefb7e8567c9675b8b13bcf4", size = 7158451, upload-time = "2026-03-11T22:19:30.397Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/ee/45c7c1f9268b0fecdd68f9ada490bc09632b74f5f90a9be759e51a746ddc/ujson-5.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:38051f36423f084b909aaadb3b41c9c6a2958e86956ba21a8489636911e87504", size = 56145, upload-time = "2026-03-11T22:17:49.409Z" }, + { url = "https://files.pythonhosted.org/packages/6d/dc/ed181dbfb2beee598e91280c6903ba71e10362b051716317e2d3664614bb/ujson-5.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:457fabc2700a8e6ddb85bc5a1d30d3345fe0d3ec3ee8161a4e032ec585801dfa", size = 53839, upload-time = "2026-03-11T22:17:50.973Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d8/eb9ef42c660f431deeedc2e1b09c4ba29aa22818a439ddda7da6ae23ddfa/ujson-5.12.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57930ac9519099b852e190d2c04b1fb5d97ea128db33bce77ed874eccb4c7f09", size = 57844, upload-time = "2026-03-11T22:17:53.029Z" }, + { url = "https://files.pythonhosted.org/packages/68/37/0b586d079d3f2a5be5aa58ab5c423cbb4fae2ee4e65369c87aa74ac7e113/ujson-5.12.0-cp310-cp310-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:9b3b86ec3e818f3dd3e13a9de628e88a9990f4af68ecb0b12dd3de81227f0a26", size = 59923, upload-time = "2026-03-11T22:17:54.332Z" }, + { url = "https://files.pythonhosted.org/packages/28/ed/6a4b69eb397502767f438b5a2b4c066dccc9e3b263115f5ee07510250fc7/ujson-5.12.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:460e76a4daff214ae33ab959494962c93918cb44714ea3e3f748b14aa37f8a87", size = 57427, upload-time = "2026-03-11T22:17:55.317Z" }, + { url = "https://files.pythonhosted.org/packages/bb/4b/ae118440a72e85e68ee8dd26cfc47ea7857954a3341833cde9da7dc40ca3/ujson-5.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e584d0cdd37cac355aca52ed788d1a2d939d6837e2870d3b70e585db24025a50", size = 1037301, upload-time = "2026-03-11T22:17:56.427Z" }, + { url = "https://files.pythonhosted.org/packages/c2/76/834caa7905f65d3a695e4f5ff8d5d4a98508e396a9e8ab0739ab4fe2d422/ujson-5.12.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0fe9128e75c6aa6e9ae06c1408d6edd9179a2fef0fe6d9cda3166b887eba521d", size = 1196664, upload-time = "2026-03-11T22:17:58.061Z" }, + { url = "https://files.pythonhosted.org/packages/f2/33/1f3c1543c1d3f18c54bb3f8c1e74314fd6ad3c1aa375f01433e89a86bfa6/ujson-5.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3ed5cb149892141b1e77ef312924a327f2cc718b34247dae346ed66329e1b8be", size = 1089668, upload-time = "2026-03-11T22:17:59.617Z" }, + { url = "https://files.pythonhosted.org/packages/db/52/07d9da456a78296f61893b9d2bbfb2512f4233394748aae80b8d08c7d96e/ujson-5.12.0-cp310-cp310-win32.whl", hash = "sha256:973b7d7145b1ac553a7466a64afa8b31ec2693d7c7fff6a755059e0a2885dfd2", size = 39644, upload-time = "2026-03-11T22:18:01.212Z" }, + { url = "https://files.pythonhosted.org/packages/ec/e5/c1de3041672fa1ab97aae0f0b9f4e30a9b15d4104c734d5627779206c878/ujson-5.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:1d072a403d82aef8090c6d4f728e3a727dfdba1ad3b7fa3a052c3ecbd37e73cb", size = 43875, upload-time = "2026-03-11T22:18:02.268Z" }, + { url = "https://files.pythonhosted.org/packages/8b/49/714a9240d9e6bd86c9684a72f100a0005459165fb2b0f6bf1a1156be0b9f/ujson-5.12.0-cp310-cp310-win_arm64.whl", hash = "sha256:55ede2a7a051b3b7e71a394978a098d71b3783e6b904702ff45483fad434ae2d", size = 38563, upload-time = "2026-03-11T22:18:03.546Z" }, + { url = "https://files.pythonhosted.org/packages/10/22/fd22e2f6766bae934d3050517ca47d463016bd8688508d1ecc1baa18a7ad/ujson-5.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58a11cb49482f1a095a2bd9a1d81dd7c8fb5d2357f959ece85db4e46a825fd00", size = 56139, upload-time = "2026-03-11T22:18:04.591Z" }, + { url = "https://files.pythonhosted.org/packages/c6/fd/6839adff4fc0164cbcecafa2857ba08a6eaeedd7e098d6713cb899a91383/ujson-5.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9b3cf13facf6f77c283af0e1713e5e8c47a0fe295af81326cb3cb4380212e797", size = 53836, upload-time = "2026-03-11T22:18:05.662Z" }, + { url = "https://files.pythonhosted.org/packages/f9/b0/0c19faac62d68ceeffa83a08dc3d71b8462cf5064d0e7e0b15ba19898dad/ujson-5.12.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb94245a715b4d6e24689de12772b85329a1f9946cbf6187923a64ecdea39e65", size = 57851, upload-time = "2026-03-11T22:18:06.744Z" }, + { url = "https://files.pythonhosted.org/packages/04/f6/e7fd283788de73b86e99e08256726bb385923249c21dcd306e59d532a1a1/ujson-5.12.0-cp311-cp311-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:0fe6b8b8968e11dd9b2348bd508f0f57cf49ab3512064b36bc4117328218718e", size = 59906, upload-time = "2026-03-11T22:18:07.791Z" }, + { url = "https://files.pythonhosted.org/packages/d7/3a/b100735a2b43ee6e8fe4c883768e362f53576f964d4ea841991060aeaf35/ujson-5.12.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89e302abd3749f6d6699691747969a5d85f7c73081d5ed7e2624c7bd9721a2ab", size = 57409, upload-time = "2026-03-11T22:18:08.79Z" }, + { url = "https://files.pythonhosted.org/packages/5c/fa/f97cc20c99ca304662191b883ae13ae02912ca7244710016ba0cb8a5be34/ujson-5.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0727363b05ab05ee737a28f6200dc4078bce6b0508e10bd8aab507995a15df61", size = 1037339, upload-time = "2026-03-11T22:18:10.424Z" }, + { url = "https://files.pythonhosted.org/packages/10/7a/53ddeda0ffe1420db2f9999897b3cbb920fbcff1849d1f22b196d0f34785/ujson-5.12.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b62cb9a7501e1f5c9ffe190485501349c33e8862dde4377df774e40b8166871f", size = 1196625, upload-time = "2026-03-11T22:18:11.82Z" }, + { url = "https://files.pythonhosted.org/packages/0d/1a/4c64a6bef522e9baf195dd5be151bc815cd4896c50c6e2489599edcda85f/ujson-5.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a6ec5bf6bc361f2f0f9644907a36ce527715b488988a8df534120e5c34eeda94", size = 1089669, upload-time = "2026-03-11T22:18:13.343Z" }, + { url = "https://files.pythonhosted.org/packages/18/11/8ccb109f5777ec0d9fb826695a9e2ac36ae94c1949fc8b1e4d23a5bd067a/ujson-5.12.0-cp311-cp311-win32.whl", hash = "sha256:006428d3813b87477d72d306c40c09f898a41b968e57b15a7d88454ecc42a3fb", size = 39648, upload-time = "2026-03-11T22:18:14.785Z" }, + { url = "https://files.pythonhosted.org/packages/6f/e3/87fc4c27b20d5125cff7ce52d17ea7698b22b74426da0df238e3efcb0cf2/ujson-5.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:40aa43a7a3a8d2f05e79900858053d697a88a605e3887be178b43acbcd781161", size = 43876, upload-time = "2026-03-11T22:18:15.768Z" }, + { url = "https://files.pythonhosted.org/packages/9e/21/324f0548a8c8c48e3e222eaed15fb6d48c796593002b206b4a28a89e445f/ujson-5.12.0-cp311-cp311-win_arm64.whl", hash = "sha256:561f89cc82deeae82e37d4a4764184926fb432f740a9691563a391b13f7339a4", size = 38553, upload-time = "2026-03-11T22:18:17.251Z" }, + { url = "https://files.pythonhosted.org/packages/84/f6/ac763d2108d28f3a40bb3ae7d2fafab52ca31b36c2908a4ad02cd3ceba2a/ujson-5.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:09b4beff9cc91d445d5818632907b85fb06943b61cb346919ce202668bf6794a", size = 56326, upload-time = "2026-03-11T22:18:18.467Z" }, + { url = "https://files.pythonhosted.org/packages/25/46/d0b3af64dcdc549f9996521c8be6d860ac843a18a190ffc8affeb7259687/ujson-5.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ca0c7ce828bb76ab78b3991904b477c2fd0f711d7815c252d1ef28ff9450b052", size = 53910, upload-time = "2026-03-11T22:18:19.502Z" }, + { url = "https://files.pythonhosted.org/packages/9a/10/853c723bcabc3e9825a079019055fc99e71b85c6bae600607a2b9d31d18d/ujson-5.12.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2d79c6635ccffcbfc1d5c045874ba36b594589be81d50d43472570bb8de9c57", size = 57754, upload-time = "2026-03-11T22:18:20.874Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c6/6e024830d988f521f144ead641981c1f7a82c17ad1927c22de3242565f5c/ujson-5.12.0-cp312-cp312-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:7e07f6f644d2c44d53b7a320a084eef98063651912c1b9449b5f45fcbdc6ccd2", size = 59936, upload-time = "2026-03-11T22:18:21.924Z" }, + { url = "https://files.pythonhosted.org/packages/34/c9/c5f236af5abe06b720b40b88819d00d10182d2247b1664e487b3ed9229cf/ujson-5.12.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:085b6ce182cdd6657481c7c4003a417e0655c4f6e58b76f26ee18f0ae21db827", size = 57463, upload-time = "2026-03-11T22:18:22.924Z" }, + { url = "https://files.pythonhosted.org/packages/ae/04/41342d9ef68e793a87d84e4531a150c2b682f3bcedfe59a7a5e3f73e9213/ujson-5.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:16b4fe9c97dc605f5e1887a9e1224287291e35c56cbc379f8aa44b6b7bcfe2bb", size = 1037239, upload-time = "2026-03-11T22:18:24.04Z" }, + { url = "https://files.pythonhosted.org/packages/d4/81/dc2b7617d5812670d4ff4a42f6dd77926430ee52df0dedb2aec7990b2034/ujson-5.12.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0d2e8db5ade3736a163906154ca686203acc7d1d30736cbf577c730d13653d84", size = 1196713, upload-time = "2026-03-11T22:18:25.391Z" }, + { url = "https://files.pythonhosted.org/packages/b6/9c/80acff0504f92459ed69e80a176286e32ca0147ac6a8252cd0659aad3227/ujson-5.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:93bc91fdadcf046da37a214eaa714574e7e9b1913568e93bb09527b2ceb7f759", size = 1089742, upload-time = "2026-03-11T22:18:26.738Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f0/123ffaac17e45ef2b915e3e3303f8f4ea78bb8d42afad828844e08622b1e/ujson-5.12.0-cp312-cp312-win32.whl", hash = "sha256:2a248750abce1c76fbd11b2e1d88b95401e72819295c3b851ec73399d6849b3d", size = 39773, upload-time = "2026-03-11T22:18:28.244Z" }, + { url = "https://files.pythonhosted.org/packages/b5/20/f3bd2b069c242c2b22a69e033bfe224d1d15d3649e6cd7cc7085bb1412ff/ujson-5.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:1b5c6ceb65fecd28a1d20d1eba9dbfa992612b86594e4b6d47bb580d2dd6bcb3", size = 44040, upload-time = "2026-03-11T22:18:29.236Z" }, + { url = "https://files.pythonhosted.org/packages/f0/a7/01b5a0bcded14cd2522b218f2edc3533b0fcbccdea01f3e14a2b699071aa/ujson-5.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:9a5fcbe7b949f2e95c47ea8a80b410fcdf2da61c98553b45a4ee875580418b68", size = 38526, upload-time = "2026-03-11T22:18:30.551Z" }, + { url = "https://files.pythonhosted.org/packages/3f/f1/0ef0eeab1db8493e1833c8b440fe32cf7538f7afa6e7f7c7e9f62cef464d/ujson-5.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:15d416440148f3e56b9b244fdaf8a09fcf5a72e4944b8e119f5bf60417a2bfc8", size = 56331, upload-time = "2026-03-11T22:18:31.539Z" }, + { url = "https://files.pythonhosted.org/packages/b0/2f/9159f6f399b3f572d20847a2b80d133e3a03c14712b0da4971a36879fb64/ujson-5.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e0dd3676ea0837cd70ea1879765e9e9f6be063be0436de9b3ea4b775caf83654", size = 53910, upload-time = "2026-03-11T22:18:32.829Z" }, + { url = "https://files.pythonhosted.org/packages/e5/a9/f96376818d71495d1a4be19a0ab6acf0cc01dd8826553734c3d4dac685b2/ujson-5.12.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7bbf05c38debc90d1a195b11340cc85cb43ab3e753dc47558a3a84a38cbc72da", size = 57757, upload-time = "2026-03-11T22:18:33.866Z" }, + { url = "https://files.pythonhosted.org/packages/98/8d/dd4a151caac6fdcb77f024fbe7f09d465ebf347a628ed6dd581a0a7f6364/ujson-5.12.0-cp313-cp313-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:3c2f947e55d3c7cfe124dd4521ee481516f3007d13c6ad4bf6aeb722e190eb1b", size = 59940, upload-time = "2026-03-11T22:18:35.276Z" }, + { url = "https://files.pythonhosted.org/packages/c7/17/0d36c2fee0a8d8dc37b011ccd5bbdcfaff8b8ec2bcfc5be998661cdc935b/ujson-5.12.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ea6206043385343aff0b7da65cf73677f6f5e50de8f1c879e557f4298cac36a", size = 57465, upload-time = "2026-03-11T22:18:36.644Z" }, + { url = "https://files.pythonhosted.org/packages/8c/04/b0ee4a4b643a01ba398441da1e357480595edb37c6c94c508dbe0eb9eb60/ujson-5.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bb349dbba57c76eec25e5917e07f35aabaf0a33b9e67fc13d188002500106487", size = 1037236, upload-time = "2026-03-11T22:18:37.743Z" }, + { url = "https://files.pythonhosted.org/packages/2d/08/0e7780d0bbb48fe57ded91f550144bcc99c03b5360bf2886dd0dae0ea8f5/ujson-5.12.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:937794042342006f707837f38d721426b11b0774d327a2a45c0bd389eb750a87", size = 1196717, upload-time = "2026-03-11T22:18:39.101Z" }, + { url = "https://files.pythonhosted.org/packages/ba/4c/e0e34107715bb4dd2d4dcc1ce244d2f074638837adf38aff85a37506efe4/ujson-5.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6ad57654570464eb1b040b5c353dee442608e06cff9102b8fcb105565a44c9ed", size = 1089748, upload-time = "2026-03-11T22:18:40.473Z" }, + { url = "https://files.pythonhosted.org/packages/72/43/814f4e2b5374d0d505c254ba4bed43eb25d2d046f19f5fd88555f81a7bd0/ujson-5.12.0-cp313-cp313-win32.whl", hash = "sha256:76bf3e7406cf23a3e1ca6a23fb1fb9ea82f4f6bd226fe226e09146b0194f85dc", size = 39778, upload-time = "2026-03-11T22:18:41.791Z" }, + { url = "https://files.pythonhosted.org/packages/0f/fe/19310d848ebe93315b6cb171277e4ce29f47ef9d46caabd63ff05d5be548/ujson-5.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:15e555c4caca42411270b2ed2b2ebc7b3a42bb04138cef6c956e1f1d49709fe2", size = 44038, upload-time = "2026-03-11T22:18:43.094Z" }, + { url = "https://files.pythonhosted.org/packages/3f/e4/7a39103d7634691601a02bd1ca7268fba4da47ed586365e6ee68168f575a/ujson-5.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:bd03472c36fa3a386a6deb887113b9e3fa40efba8203eb4fe786d3c0ccc724f6", size = 38529, upload-time = "2026-03-11T22:18:44.167Z" }, + { url = "https://files.pythonhosted.org/packages/10/bd/9a8d693254bada62bfea75a507e014afcfdb6b9d047b6f8dd134bfefaf67/ujson-5.12.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:85833bca01aa5cae326ac759276dc175c5fa3f7b3733b7d543cf27f2df12d1ef", size = 56499, upload-time = "2026-03-11T22:18:45.431Z" }, + { url = "https://files.pythonhosted.org/packages/bd/2d/285a83df8176e18dcd675d1a4cff8f7620f003f30903ea43929406e98986/ujson-5.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d22cad98c2a10bbf6aa083a8980db6ed90d4285a841c4de892890c2b28286ef9", size = 53998, upload-time = "2026-03-11T22:18:47.184Z" }, + { url = "https://files.pythonhosted.org/packages/bf/8b/e2f09e16dabfa91f6a84555df34a4329fa7621e92ed054d170b9054b9bb2/ujson-5.12.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99cc80facad240b0c2fb5a633044420878aac87a8e7c348b9486450cba93f27c", size = 57783, upload-time = "2026-03-11T22:18:48.271Z" }, + { url = "https://files.pythonhosted.org/packages/68/fb/ba1d06f3658a0c36d0ab3869ec3914f202bad0a9bde92654e41516c7bb13/ujson-5.12.0-cp314-cp314-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:d1831c07bd4dce53c4b666fa846c7eba4b7c414f2e641a4585b7f50b72f502dc", size = 60011, upload-time = "2026-03-11T22:18:49.284Z" }, + { url = "https://files.pythonhosted.org/packages/64/2b/3e322bf82d926d9857206cd5820438d78392d1f523dacecb8bd899952f73/ujson-5.12.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e00cec383eab2406c9e006bd4edb55d284e94bb943fda558326048178d26961", size = 57465, upload-time = "2026-03-11T22:18:50.584Z" }, + { url = "https://files.pythonhosted.org/packages/e9/fd/af72d69603f9885e5136509a529a4f6d88bf652b457263ff96aefcd3ab7d/ujson-5.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f19b3af31d02a2e79c5f9a6deaab0fb3c116456aeb9277d11720ad433de6dfc6", size = 1037275, upload-time = "2026-03-11T22:18:51.998Z" }, + { url = "https://files.pythonhosted.org/packages/9c/a7/a2411ec81aef7872578e56304c3e41b3a544a9809e95c8e1df46923fc40b/ujson-5.12.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:bacbd3c69862478cbe1c7ed4325caedec580d8acf31b8ee1b9a1e02a56295cad", size = 1196758, upload-time = "2026-03-11T22:18:53.548Z" }, + { url = "https://files.pythonhosted.org/packages/ed/85/aa18ae175dd03a118555aa14304d4f466f9db61b924c97c6f84388ecacb1/ujson-5.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94c5f1621cbcab83c03be46441f090b68b9f307b6c7ec44d4e3f6d5997383df4", size = 1089760, upload-time = "2026-03-11T22:18:55.336Z" }, + { url = "https://files.pythonhosted.org/packages/d3/d4/4b40b67ac7e916ebffc3041ae2320c5c0b8a045300d4c542b6e50930cca5/ujson-5.12.0-cp314-cp314-win32.whl", hash = "sha256:e6369ac293d2cc40d52577e4fa3d75a70c1aae2d01fa3580a34a4e6eff9286b9", size = 41043, upload-time = "2026-03-11T22:18:56.505Z" }, + { url = "https://files.pythonhosted.org/packages/24/38/a1496d2a3428981f2b3a2ffbb4656c2b05be6cc406301d6b10a6445f6481/ujson-5.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:31348a0ffbfc815ce78daac569d893349d85a0b57e1cd2cdbba50b7f333784da", size = 45303, upload-time = "2026-03-11T22:18:57.454Z" }, + { url = "https://files.pythonhosted.org/packages/85/d3/39dbd3159543d9c57ec3a82d36226152cf0d710784894ce5aa24b8220ac1/ujson-5.12.0-cp314-cp314-win_arm64.whl", hash = "sha256:6879aed770557f0961b252648d36f6fdaab41079d37a2296b5649fd1b35608e0", size = 39860, upload-time = "2026-03-11T22:18:58.578Z" }, + { url = "https://files.pythonhosted.org/packages/c3/71/9b4dacb177d3509077e50497222d39eec04c8b41edb1471efc764d645237/ujson-5.12.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7ddb08b3c2f9213df1f2e3eb2fbea4963d80ec0f8de21f0b59898e34f3b3d96d", size = 56845, upload-time = "2026-03-11T22:18:59.629Z" }, + { url = "https://files.pythonhosted.org/packages/24/c2/8abffa3be1f3d605c4a62445fab232b3e7681512ce941c6b23014f404d36/ujson-5.12.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0a3ae28f0b209be5af50b54ca3e2123a3de3a57d87b75f1e5aa3d7961e041983", size = 54463, upload-time = "2026-03-11T22:19:00.697Z" }, + { url = "https://files.pythonhosted.org/packages/db/2e/60114a35d1d6796eb428f7affcba00a921831ff604a37d9142c3d8bbe5c5/ujson-5.12.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d30ad4359413c8821cc7b3707f7ca38aa8bc852ba3b9c5a759ee2d7740157315", size = 58689, upload-time = "2026-03-11T22:19:01.739Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ad/010925c2116c21ce119f9c2ff18d01f48a19ade3ff4c5795da03ce5829fc/ujson-5.12.0-cp314-cp314t-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:02f93da7a4115e24f886b04fd56df1ee8741c2ce4ea491b7ab3152f744ad8f8e", size = 60618, upload-time = "2026-03-11T22:19:03.101Z" }, + { url = "https://files.pythonhosted.org/packages/9b/74/db7f638bf20282b1dccf454386cbd483faaaed3cdbb9cb27e06f74bb109e/ujson-5.12.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3ff4ede90ed771140caa7e1890de17431763a483c54b3c1f88bd30f0cc1affc0", size = 58151, upload-time = "2026-03-11T22:19:04.175Z" }, + { url = "https://files.pythonhosted.org/packages/9c/7e/3ebaecfa70a2e8ce623db8e21bd5cb05d42a5ef943bcbb3309d71b5de68d/ujson-5.12.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a7bf9cc97f05048ac8f3e02cd58f0fe62b901453c24345bfde287f4305dcc31c", size = 1038117, upload-time = "2026-03-11T22:19:05.558Z" }, + { url = "https://files.pythonhosted.org/packages/2e/aa/e073eda7f0036c2973b28db7bb99faba17a932e7b52d801f9bb3e726271f/ujson-5.12.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:2324d9a0502317ffc35d38e153c1b2fa9610ae03775c9d0f8d0cca7b8572b04e", size = 1197434, upload-time = "2026-03-11T22:19:06.92Z" }, + { url = "https://files.pythonhosted.org/packages/1c/01/b9a13f058fdd50c746b192c4447ca8d6352e696dcda912ccee10f032ff85/ujson-5.12.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:50524f4f6a1c839714dbaff5386a1afb245d2d5ec8213a01fbc99cea7307811e", size = 1090401, upload-time = "2026-03-11T22:19:08.383Z" }, + { url = "https://files.pythonhosted.org/packages/c4/37/3d1b4e0076b6e43379600b5229a5993db8a759ff2e1830ea635d876f6644/ujson-5.12.0-cp314-cp314t-win32.whl", hash = "sha256:f7a0430d765f9bda043e6aefaba5944d5f21ec43ff4774417d7e296f61917382", size = 41880, upload-time = "2026-03-11T22:19:09.671Z" }, + { url = "https://files.pythonhosted.org/packages/b1/c5/3c2a262a138b9f0014fe1134a6b5fdc2c54245030affbaac2fcbc0632138/ujson-5.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:ccbfd94e59aad4a2566c71912b55f0547ac1680bfac25eb138e6703eb3dd434e", size = 46365, upload-time = "2026-03-11T22:19:10.662Z" }, + { url = "https://files.pythonhosted.org/packages/83/40/956dc20b7e00dc0ff3259871864f18dab211837fce3478778bedb3132ac1/ujson-5.12.0-cp314-cp314t-win_arm64.whl", hash = "sha256:42d875388fbd091c7ea01edfff260f839ba303038ffb23475ef392012e4d63dd", size = 40398, upload-time = "2026-03-11T22:19:11.666Z" }, + { url = "https://files.pythonhosted.org/packages/95/3c/5ee154d505d1aad2debc4ba38b1a60ae1949b26cdb5fa070e85e320d6b64/ujson-5.12.0-graalpy312-graalpy250_312_native-macosx_10_13_x86_64.whl", hash = "sha256:bf85a00ac3b56a1e7a19c5be7b02b5180a0895ac4d3c234d717a55e86960691c", size = 54494, upload-time = "2026-03-11T22:19:13.035Z" }, + { url = "https://files.pythonhosted.org/packages/ce/b3/9496ec399ec921e434a93b340bd5052999030b7ac364be4cbe5365ac6b20/ujson-5.12.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:64df53eef4ac857eb5816a56e2885ccf0d7dff6333c94065c93b39c51063e01d", size = 57999, upload-time = "2026-03-11T22:19:14.385Z" }, + { url = "https://files.pythonhosted.org/packages/0e/da/e9ae98133336e7c0d50b43626c3f2327937cecfa354d844e02ac17379ed1/ujson-5.12.0-graalpy312-graalpy250_312_native-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6c0aed6a4439994c9666fb8a5b6c4eac94d4ef6ddc95f9b806a599ef83547e3b", size = 54518, upload-time = "2026-03-11T22:19:15.4Z" }, + { url = "https://files.pythonhosted.org/packages/58/10/978d89dded6bb1558cd46ba78f4351198bd2346db8a8ee1a94119022ce40/ujson-5.12.0-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efae5df7a8cc8bdb1037b0f786b044ce281081441df5418c3a0f0e1f86fe7bb3", size = 55736, upload-time = "2026-03-11T22:19:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/80/25/1df8e6217c92e57a1266bf5be750b1dddc126ee96e53fe959d5693503bc6/ujson-5.12.0-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:8712b61eb1b74a4478cfd1c54f576056199e9f093659334aeb5c4a6b385338e5", size = 44615, upload-time = "2026-03-11T22:19:17.53Z" }, + { url = "https://files.pythonhosted.org/packages/19/fa/f4a957dddb99bd68c8be91928c0b6fefa7aa8aafc92c93f5d1e8b32f6702/ujson-5.12.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:871c0e5102e47995b0e37e8df7819a894a6c3da0d097545cd1f9f1f7d7079927", size = 52145, upload-time = "2026-03-11T22:19:18.566Z" }, + { url = "https://files.pythonhosted.org/packages/55/6e/50b5cf612de1ca06c7effdc5a5d7e815774dee85a5858f1882c425553b82/ujson-5.12.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:56ba3f7abbd6b0bb282a544dc38406d1a188d8bb9164f49fdb9c2fee62cb29da", size = 49577, upload-time = "2026-03-11T22:19:19.627Z" }, + { url = "https://files.pythonhosted.org/packages/6e/24/b6713fa9897774502cd4c2d6955bb4933349f7d84c3aa805531c382a4209/ujson-5.12.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c5a52987a990eb1bae55f9000994f1afdb0326c154fb089992f839ab3c30688", size = 50807, upload-time = "2026-03-11T22:19:20.778Z" }, + { url = "https://files.pythonhosted.org/packages/1f/b6/c0e0f7901180ef80d16f3a4bccb5dc8b01515a717336a62928963a07b80b/ujson-5.12.0-pp311-pypy311_pp73-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:adf28d13a33f9d750fe7a78fb481cac298fa257d8863d8727b2ea4455ea41235", size = 56972, upload-time = "2026-03-11T22:19:21.84Z" }, + { url = "https://files.pythonhosted.org/packages/02/a9/05d91b4295ea7239151eb08cf240e5a2ba969012fda50bc27bcb1ea9cd71/ujson-5.12.0-pp311-pypy311_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51acc750ec7a2df786cdc868fb16fa04abd6269a01d58cf59bafc57978773d8e", size = 52045, upload-time = "2026-03-11T22:19:22.879Z" }, + { url = "https://files.pythonhosted.org/packages/e3/7a/92047d32bf6f2d9db64605fc32e8eb0e0dd68b671eaafc12a464f69c4af4/ujson-5.12.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:ab9056d94e5db513d9313b34394f3a3b83e6301a581c28ad67773434f3faccab", size = 44053, upload-time = "2026-03-11T22:19:23.918Z" }, ] [[package]] From 6cd66ace1cb62ace58d1b7c3d5087e1794da62cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 16:00:21 +0100 Subject: [PATCH 10/69] =?UTF-8?q?=E2=AC=86=20Bump=20pyasn1=20from=200.6.2?= =?UTF-8?q?=20to=200.6.3=20(#15143)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index 4c16fe10a9..aec021dd26 100644 --- a/uv.lock +++ b/uv.lock @@ -3941,11 +3941,11 @@ wheels = [ [[package]] name = "pyasn1" -version = "0.6.2" +version = "0.6.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fe/b6/6e630dff89739fcd427e3f72b3d905ce0acb85a45d4ec3e2678718a3487f/pyasn1-0.6.2.tar.gz", hash = "sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b", size = 146586, upload-time = "2026-01-16T18:04:18.534Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/5f/6583902b6f79b399c9c40674ac384fd9cd77805f9e6205075f828ef11fb2/pyasn1-0.6.3.tar.gz", hash = "sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf", size = 148685, upload-time = "2026-03-17T01:06:53.382Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/44/b5/a96872e5184f354da9c84ae119971a0a4c221fe9b27a4d94bd43f2596727/pyasn1-0.6.2-py3-none-any.whl", hash = "sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf", size = 83371, upload-time = "2026-01-16T18:04:17.174Z" }, + { url = "https://files.pythonhosted.org/packages/5d/a0/7d793dce3fa811fe047d6ae2431c672364b462850c6235ae306c0efd025f/pyasn1-0.6.3-py3-none-any.whl", hash = "sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde", size = 83997, upload-time = "2026-03-17T01:06:52.036Z" }, ] [[package]] From a4e005c1400ce09281c6fabc3a8d6bfee19240ca Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Mar 2026 15:00:28 +0000 Subject: [PATCH 11/69] =?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 a0c527b984..05b98c8b22 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -42,6 +42,7 @@ hide: ### Internal +* ⬆ Bump ujson from 5.11.0 to 5.12.0. PR [#15150](https://github.com/fastapi/fastapi/pull/15150) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔨 Tweak translation workflow and translation fixer tool. PR [#15166](https://github.com/fastapi/fastapi/pull/15166) by [@YuriiMotov](https://github.com/YuriiMotov). * 🔨 Fix `commit_in_place` passed via env variable in `translate.yml` workflow. PR [#15151](https://github.com/fastapi/fastapi/pull/15151) by [@YuriiMotov](https://github.com/YuriiMotov). * 🔨 Update translation general prompt to enforce link style in translation matches the original link style. PR [#15148](https://github.com/fastapi/fastapi/pull/15148) by [@YuriiMotov](https://github.com/YuriiMotov). From 30bd2d5878506b63617f47ac0fc22aa836bde575 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Mar 2026 15:02:05 +0000 Subject: [PATCH 12/69] =?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 05b98c8b22..78d8183685 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -42,6 +42,7 @@ hide: ### Internal +* ⬆ Bump pyasn1 from 0.6.2 to 0.6.3. PR [#15143](https://github.com/fastapi/fastapi/pull/15143) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump ujson from 5.11.0 to 5.12.0. PR [#15150](https://github.com/fastapi/fastapi/pull/15150) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔨 Tweak translation workflow and translation fixer tool. PR [#15166](https://github.com/fastapi/fastapi/pull/15166) by [@YuriiMotov](https://github.com/YuriiMotov). * 🔨 Fix `commit_in_place` passed via env variable in `translate.yml` workflow. PR [#15151](https://github.com/fastapi/fastapi/pull/15151) by [@YuriiMotov](https://github.com/YuriiMotov). From 602ddc2e514f767084f95b7985aee92da2422877 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 16:28:53 +0100 Subject: [PATCH 13/69] =?UTF-8?q?=E2=AC=86=20Bump=20authlib=20from=201.6.7?= =?UTF-8?q?=20to=201.6.9=20(#15128)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sofie Van Landeghem --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index aec021dd26..096b0a361c 100644 --- a/uv.lock +++ b/uv.lock @@ -314,14 +314,14 @@ wheels = [ [[package]] name = "authlib" -version = "1.6.7" +version = "1.6.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/49/dc/ed1681bf1339dd6ea1ce56136bad4baabc6f7ad466e375810702b0237047/authlib-1.6.7.tar.gz", hash = "sha256:dbf10100011d1e1b34048c9d120e83f13b35d69a826ae762b93d2fb5aafc337b", size = 164950, upload-time = "2026-02-06T14:04:14.171Z" } +sdist = { url = "https://files.pythonhosted.org/packages/af/98/00d3dd826d46959ad8e32af2dbb2398868fd9fd0683c26e56d0789bd0e68/authlib-1.6.9.tar.gz", hash = "sha256:d8f2421e7e5980cc1ddb4e32d3f5fa659cfaf60d8eaf3281ebed192e4ab74f04", size = 165134, upload-time = "2026-03-02T07:44:01.998Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f8/00/3ed12264094ec91f534fae429945efbaa9f8c666f3aa7061cc3b2a26a0cd/authlib-1.6.7-py2.py3-none-any.whl", hash = "sha256:c637340d9a02789d2efa1d003a7437d10d3e565237bcb5fcbc6c134c7b95bab0", size = 244115, upload-time = "2026-02-06T14:04:12.141Z" }, + { url = "https://files.pythonhosted.org/packages/53/23/b65f568ed0c22f1efacb744d2db1a33c8068f384b8c9b482b52ebdbc3ef6/authlib-1.6.9-py2.py3-none-any.whl", hash = "sha256:f08b4c14e08f0861dc18a32357b33fbcfd2ea86cfe3fe149484b4d764c4a0ac3", size = 244197, upload-time = "2026-03-02T07:44:00.307Z" }, ] [[package]] From b7bd1874fe8fb17bc414dc6dfe8e1b92f41a2d1f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Mar 2026 15:29:22 +0000 Subject: [PATCH 14/69] =?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 78d8183685..772f81eb68 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -42,6 +42,7 @@ hide: ### Internal +* ⬆ Bump authlib from 1.6.7 to 1.6.9. PR [#15128](https://github.com/fastapi/fastapi/pull/15128) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pyasn1 from 0.6.2 to 0.6.3. PR [#15143](https://github.com/fastapi/fastapi/pull/15143) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump ujson from 5.11.0 to 5.12.0. PR [#15150](https://github.com/fastapi/fastapi/pull/15150) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔨 Tweak translation workflow and translation fixer tool. PR [#15166](https://github.com/fastapi/fastapi/pull/15166) by [@YuriiMotov](https://github.com/YuriiMotov). From fe98ea307a6664ae811bbfe8db9e81f048556f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 20 Mar 2026 18:05:38 +0100 Subject: [PATCH 15/69] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20fo?= =?UTF-8?q?r=20zh-hant=20(update-outdated)=20(#15178)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov --- docs/zh-hant/docs/_llm-test.md | 18 +-- .../docs/advanced/additional-responses.md | 4 +- .../docs/advanced/additional-status-codes.md | 4 +- .../docs/advanced/advanced-dependencies.md | 4 +- docs/zh-hant/docs/advanced/async-tests.md | 8 +- docs/zh-hant/docs/advanced/behind-a-proxy.md | 26 ++-- docs/zh-hant/docs/advanced/custom-response.md | 114 ++++++---------- docs/zh-hant/docs/advanced/dataclasses.md | 8 +- docs/zh-hant/docs/advanced/events.md | 6 +- .../zh-hant/docs/advanced/generate-clients.md | 18 +-- docs/zh-hant/docs/advanced/index.md | 6 +- docs/zh-hant/docs/advanced/middleware.md | 10 +- .../docs/advanced/openapi-callbacks.md | 10 +- .../zh-hant/docs/advanced/openapi-webhooks.md | 2 +- .../path-operation-advanced-configuration.md | 6 +- .../advanced/response-change-status-code.md | 4 +- .../zh-hant/docs/advanced/response-cookies.md | 4 +- .../docs/advanced/response-directly.md | 30 ++++- .../zh-hant/docs/advanced/response-headers.md | 6 +- .../docs/advanced/security/http-basic-auth.md | 2 +- docs/zh-hant/docs/advanced/security/index.md | 6 +- .../docs/advanced/security/oauth2-scopes.md | 4 +- docs/zh-hant/docs/advanced/settings.md | 16 +-- .../zh-hant/docs/advanced/sub-applications.md | 10 +- docs/zh-hant/docs/advanced/templates.md | 4 +- .../docs/advanced/testing-websockets.md | 2 +- .../docs/advanced/using-request-directly.md | 4 +- docs/zh-hant/docs/advanced/websockets.md | 22 ++-- docs/zh-hant/docs/advanced/wsgi.md | 6 +- docs/zh-hant/docs/alternatives.md | 60 ++++----- docs/zh-hant/docs/async.md | 26 ++-- docs/zh-hant/docs/benchmarks.md | 2 +- docs/zh-hant/docs/deployment/cloud.md | 8 +- docs/zh-hant/docs/deployment/concepts.md | 8 +- docs/zh-hant/docs/deployment/docker.md | 46 +++---- docs/zh-hant/docs/deployment/fastapicloud.md | 4 +- docs/zh-hant/docs/deployment/https.md | 16 +-- docs/zh-hant/docs/deployment/index.md | 2 +- docs/zh-hant/docs/deployment/manually.md | 12 +- .../zh-hant/docs/deployment/server-workers.md | 6 +- docs/zh-hant/docs/deployment/versions.md | 6 +- docs/zh-hant/docs/environment-variables.md | 10 +- docs/zh-hant/docs/fastapi-cli.md | 71 ++++++++-- docs/zh-hant/docs/features.md | 26 ++-- docs/zh-hant/docs/help-fastapi.md | 58 ++++----- docs/zh-hant/docs/history-design-future.md | 14 +- .../authentication-error-status-code.md | 2 +- .../docs/how-to/conditional-openapi.md | 2 +- .../docs/how-to/configure-swagger-ui.md | 8 +- .../docs/how-to/custom-docs-ui-assets.md | 12 +- .../docs/how-to/custom-request-and-route.md | 10 +- docs/zh-hant/docs/how-to/extending-openapi.md | 4 +- docs/zh-hant/docs/how-to/general.md | 22 ++-- docs/zh-hant/docs/how-to/graphql.md | 30 ++--- docs/zh-hant/docs/how-to/index.md | 2 +- ...migrate-from-pydantic-v1-to-pydantic-v2.md | 6 +- docs/zh-hant/docs/how-to/testing-database.md | 6 +- docs/zh-hant/docs/index.md | 122 ++++++++---------- docs/zh-hant/docs/project-generation.md | 2 +- docs/zh-hant/docs/python-types.md | 10 +- .../zh-hant/docs/tutorial/background-tasks.md | 6 +- .../docs/tutorial/bigger-applications.md | 47 +++++-- .../docs/tutorial/body-nested-models.md | 2 +- docs/zh-hant/docs/tutorial/body-updates.md | 6 +- docs/zh-hant/docs/tutorial/body.md | 12 +- docs/zh-hant/docs/tutorial/cors.md | 8 +- docs/zh-hant/docs/tutorial/debugging.md | 4 +- ...pendencies-in-path-operation-decorators.md | 4 +- .../dependencies/dependencies-with-yield.md | 18 +-- .../dependencies/global-dependencies.md | 6 +- .../docs/tutorial/dependencies/index.md | 4 +- docs/zh-hant/docs/tutorial/encoder.md | 4 +- .../zh-hant/docs/tutorial/extra-data-types.md | 4 +- docs/zh-hant/docs/tutorial/extra-models.md | 6 +- docs/zh-hant/docs/tutorial/first-steps.md | 75 +++++++++-- docs/zh-hant/docs/tutorial/handling-errors.md | 2 +- docs/zh-hant/docs/tutorial/index.md | 12 +- docs/zh-hant/docs/tutorial/metadata.md | 4 +- docs/zh-hant/docs/tutorial/middleware.md | 10 +- .../tutorial/path-operation-configuration.md | 2 +- .../path-params-numeric-validations.md | 4 +- docs/zh-hant/docs/tutorial/path-params.md | 16 +-- .../tutorial/query-params-str-validations.md | 10 +- docs/zh-hant/docs/tutorial/query-params.md | 2 +- docs/zh-hant/docs/tutorial/request-files.md | 18 +-- .../docs/tutorial/request-form-models.md | 4 +- .../docs/tutorial/request-forms-and-files.md | 4 +- docs/zh-hant/docs/tutorial/request-forms.md | 6 +- docs/zh-hant/docs/tutorial/response-model.md | 9 +- .../docs/tutorial/response-status-code.md | 6 +- .../docs/tutorial/schema-extra-example.md | 8 +- .../docs/tutorial/security/first-steps.md | 10 +- .../docs/tutorial/security/oauth2-jwt.md | 10 +- .../docs/tutorial/security/simple-oauth2.md | 4 +- docs/zh-hant/docs/tutorial/sql-databases.md | 22 ++-- docs/zh-hant/docs/tutorial/static-files.md | 4 +- docs/zh-hant/docs/tutorial/testing.md | 20 +-- docs/zh-hant/docs/virtual-environments.md | 32 ++--- 98 files changed, 755 insertions(+), 647 deletions(-) diff --git a/docs/zh-hant/docs/_llm-test.md b/docs/zh-hant/docs/_llm-test.md index 85cfd22991..f4c1efca82 100644 --- a/docs/zh-hant/docs/_llm-test.md +++ b/docs/zh-hant/docs/_llm-test.md @@ -11,7 +11,7 @@ * 檢查翻譯是否正確。 * 如有需要,改進你的語言特定提示、通用提示,或英文原文。 * 然後手動修正翻譯中剩下的問題,讓它成為一個好的譯文。 -* 重新翻譯,並保留這份好的譯文。理想結果是 LLM 不再對該譯文做任何變更。這代表通用提示與你的語言特定提示已經盡可能完善(有時它仍可能做出幾個看似隨機的變更,原因是LLMs 並非決定性演算法)。 +* 重新翻譯,並保留這份好的譯文。理想結果是 LLM 不再對該譯文做任何變更。這代表通用提示與你的語言特定提示已經盡可能完善(有時它仍可能做出幾個看似隨機的變更,原因是[LLMs 並非決定性演算法](https://doublespeak.chat/#/handbook#deterministic-output))。 測試: @@ -95,7 +95,7 @@ $ fastapi run 外部連結 -* 連結到樣式 -* 連結到腳本 -* 連結到圖片 +* [內部連結](index.md#installation) +* [外部連結](https://sqlmodel.tiangolo.com/) +* [連結到樣式](https://fastapi.tiangolo.com/css/styles.css) +* [連結到腳本](https://fastapi.tiangolo.com/js/logic.js) +* [連結到圖片](https://fastapi.tiangolo.com/img/foo.jpg) 連結文字應被翻譯,連結位址應指向對應的翻譯版本: -* FastAPI 連結 +* [FastAPI 連結](https://fastapi.tiangolo.com/zh-hant/) //// @@ -291,7 +291,7 @@ Hello again. * 即時 * 標準 * 預設 -* 區分大小寫 +* 区分大小寫 * 不區分大小寫 * 提供應用程式服務 diff --git a/docs/zh-hant/docs/advanced/additional-responses.md b/docs/zh-hant/docs/advanced/additional-responses.md index bb2bf259bd..118c65e044 100644 --- a/docs/zh-hant/docs/advanced/additional-responses.md +++ b/docs/zh-hant/docs/advanced/additional-responses.md @@ -243,5 +243,5 @@ new_dict = {**old_dict, "new key": "new value"} 若要查看回應中究竟可以包含哪些內容,你可以參考 OpenAPI 規範中的這些章節: -* OpenAPI Responses 物件,其中包含 `Response Object`。 -* OpenAPI Response 物件,你可以把這裡的任何內容直接放到 `responses` 參數內各個回應中。包含 `description`、`headers`、`content`(在其中宣告不同的媒體型別與 JSON Schemas)、以及 `links`。 +* [OpenAPI Responses 物件](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object),其中包含 `Response Object`。 +* [OpenAPI Response 物件](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object),你可以把這裡的任何內容直接放到 `responses` 參數內各個回應中。包含 `description`、`headers`、`content`(在其中宣告不同的媒體型別與 JSON Schemas)、以及 `links`。 diff --git a/docs/zh-hant/docs/advanced/additional-status-codes.md b/docs/zh-hant/docs/advanced/additional-status-codes.md index 450a4705aa..0e5941a8d6 100644 --- a/docs/zh-hant/docs/advanced/additional-status-codes.md +++ b/docs/zh-hant/docs/advanced/additional-status-codes.md @@ -26,7 +26,7 @@ /// -/// note | 注意 +/// note | 技術細節 你也可以使用 `from starlette.responses import JSONResponse`。 @@ -38,4 +38,4 @@ 如果你直接回傳額外的狀態碼與回應,它們不會被包含進 OpenAPI 綱要(API 文件)中,因為 FastAPI 無法事先知道你會回傳什麼。 -但你可以在程式碼中補充文件,使用:[額外的回應](additional-responses.md){.internal-link target=_blank}。 +但你可以在程式碼中補充文件,使用:[額外的回應](additional-responses.md)。 diff --git a/docs/zh-hant/docs/advanced/advanced-dependencies.md b/docs/zh-hant/docs/advanced/advanced-dependencies.md index 472cf470b1..559ca245fa 100644 --- a/docs/zh-hant/docs/advanced/advanced-dependencies.md +++ b/docs/zh-hant/docs/advanced/advanced-dependencies.md @@ -132,7 +132,7 @@ checker(q="somequery") 如此一來,該 session 就會釋放資料庫連線,讓其他請求可以使用。 -如果你有不同的情境,需要從含有 `yield` 的相依中提早結束,請建立一個 GitHub 討論問題,描述你的具體情境,以及為何提早關閉含有 `yield` 的相依對你有幫助。 +如果你有不同的情境,需要從含有 `yield` 的相依中提早結束,請建立一個 [GitHub 討論問題](https://github.com/fastapi/fastapi/discussions/new?category=questions),描述你的具體情境,以及為何提早關閉含有 `yield` 的相依對你有幫助。 如果有令人信服的案例需要在含有 `yield` 的相依中提前關閉,我會考慮加入一種新的選項,讓你可以選擇性啟用提前關閉。 @@ -144,7 +144,7 @@ checker(q="somequery") ### 背景任務與含有 `yield` 的相依,技術細節 { #background-tasks-and-dependencies-with-yield-technical-details } -在 FastAPI 0.106.0 之前,不可能在 `yield` 之後拋出例外;含有 `yield` 的相依的結束程式碼會在回應送出之後才執行,因此[例外處理器](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} 早就已經跑完了。 +在 FastAPI 0.106.0 之前,不可能在 `yield` 之後拋出例外;含有 `yield` 的相依的結束程式碼會在回應送出之後才執行,因此[例外處理器](../tutorial/handling-errors.md#install-custom-exception-handlers) 早就已經跑完了。 當初這樣設計主要是為了允許在背景任務中使用由相依「yield」出來的同一組物件,因為結束程式碼會在背景任務結束後才執行。 diff --git a/docs/zh-hant/docs/advanced/async-tests.md b/docs/zh-hant/docs/advanced/async-tests.md index cb7430bf6e..639c42b7db 100644 --- a/docs/zh-hant/docs/advanced/async-tests.md +++ b/docs/zh-hant/docs/advanced/async-tests.md @@ -16,11 +16,11 @@ `TestClient` 在內部做了一些魔法,讓我們能在一般的 `def` 測試函式中,使用標準 pytest 來呼叫非同步的 FastAPI 應用。但當我們在非同步函式中使用它時,這個魔法就不再奏效了。也就是說,當以非同步方式執行測試時,就不能在測試函式內使用 `TestClient`。 -`TestClient` 是建立在 HTTPX 之上,所幸我們可以直接使用它來測試 API。 +`TestClient` 是建立在 [HTTPX](https://www.python-httpx.org) 之上,所幸我們可以直接使用它來測試 API。 ## 範例 { #example } -作為簡單範例,讓我們考慮與[更大型的應用](../tutorial/bigger-applications.md){.internal-link target=_blank}與[測試](../tutorial/testing.md){.internal-link target=_blank}中描述的類似檔案結構: +作為簡單範例,讓我們考慮與[更大型的應用](../tutorial/bigger-applications.md)與[測試](../tutorial/testing.md)中描述的類似檔案結構: ``` . @@ -84,7 +84,7 @@ response = client.get('/') /// warning -如果你的應用仰賴 lifespan 事件,`AsyncClient` 不會觸發這些事件。若要確保它們被觸發,請使用 florimondmanca/asgi-lifespan 的 `LifespanManager`。 +如果你的應用仰賴 lifespan 事件,`AsyncClient` 不會觸發這些事件。若要確保它們被觸發,請使用 [florimondmanca/asgi-lifespan](https://github.com/florimondmanca/asgi-lifespan#usage) 的 `LifespanManager`。 /// @@ -94,6 +94,6 @@ response = client.get('/') /// tip -如果在將非同步呼叫整合進測試時遇到 `RuntimeError: Task attached to a different loop`(例如使用 MongoDB 的 MotorClient 時),請記得:需要事件迴圈的物件只應在非同步函式內實例化,例如在 `@app.on_event("startup")` 回呼中。 +如果在將非同步呼叫整合進測試時遇到 `RuntimeError: Task attached to a different loop`(例如使用 [MongoDB 的 MotorClient](https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop) 時),請記得:需要事件迴圈的物件只應在非同步函式內實例化,例如在 `@app.on_event("startup")` 回呼中。 /// diff --git a/docs/zh-hant/docs/advanced/behind-a-proxy.md b/docs/zh-hant/docs/advanced/behind-a-proxy.md index 71a0557afd..a7f4b83b33 100644 --- a/docs/zh-hant/docs/advanced/behind-a-proxy.md +++ b/docs/zh-hant/docs/advanced/behind-a-proxy.md @@ -16,9 +16,9 @@ 代理相關的標頭有: -* X-Forwarded-For -* X-Forwarded-Proto -* X-Forwarded-Host +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) /// @@ -60,7 +60,7 @@ https://mysuperapp.com/items/ /// tip -如果你想了解更多 HTTPS 的內容,請參考指南[[關於 HTTPS](../deployment/https.md){.internal-link target=_blank}]。 +如果你想了解更多 HTTPS 的內容,請參考指南[[關於 HTTPS](../deployment/https.md)]。 /// @@ -228,7 +228,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 請記住,伺服器(Uvicorn)除了把 `root_path` 傳給應用之外,不會拿它做其他用途。 -但如果你用瀏覽器前往 http://127.0.0.1:8000/app,你會看到一般的回應: +但如果你用瀏覽器前往 [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app) ,你會看到一般的回應: ```JSON { @@ -251,9 +251,9 @@ Uvicorn 會預期代理以 `http://127.0.0.1:8000/app` 來存取 Uvicorn,而 ## 在本機使用 Traefik 測試 { #testing-locally-with-traefik } -你可以很容易地用 Traefik 在本機跑一個「移除路徑前綴」的測試。 +你可以很容易地用 [Traefik](https://docs.traefik.io/) 在本機跑一個「移除路徑前綴」的測試。 -下載 Traefik,它是一個單一的執行檔,你可以解壓縮後直接在終端機執行。 +[下載 Traefik](https://github.com/containous/traefik/releases),它是一個單一的執行檔,你可以解壓縮後直接在終端機執行。 然後建立一個 `traefik.toml` 檔案,內容如下: @@ -330,7 +330,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 ### 檢查回應 { #check-the-responses } -現在,如果你前往 Uvicorn 的埠:http://127.0.0.1:8000/app,你會看到一般的回應: +現在,如果你前往 Uvicorn 的埠:[http://127.0.0.1:8000/app](http://127.0.0.1:8000/app),你會看到一般的回應: ```JSON { @@ -345,7 +345,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 /// -接著打開使用 Traefik 埠且包含路徑前綴的 URL:http://127.0.0.1:9999/api/v1/app。 +接著打開使用 Traefik 埠且包含路徑前綴的 URL:[http://127.0.0.1:9999/api/v1/app](http://127.0.0.1:9999/api/v1/app)。 我們會得到相同的回應: @@ -370,13 +370,13 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 「正式」的存取方式應該是透過我們定義了路徑前綴的代理。因此,如我們預期,如果你直接透過 Uvicorn 供應的文件 UI、而 URL 中沒有該路徑前綴,那它不會運作,因為它預期要透過代理來存取。 -你可以在 http://127.0.0.1:8000/docs 檢查: +你可以在 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) 檢查: 但如果我們改用「正式」的 URL,也就是使用埠號 `9999` 的代理、並在 `/api/v1/docs`,它就能正確運作了!🎉 -你可以在 http://127.0.0.1:9999/api/v1/docs 檢查: +你可以在 [http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs) 檢查: @@ -433,7 +433,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 /// -在位於 http://127.0.0.1:9999/api/v1/docs 的文件 UI 中看起來會像這樣: +在位於 [http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs) 的文件 UI 中看起來會像這樣: @@ -461,6 +461,6 @@ OpenAPI 規格中的 `servers` 屬性是可選的。 ## 掛載子應用 { #mounting-a-sub-application } -如果你需要在同時使用具有 `root_path` 的代理時,掛載一個子應用(如[[子應用 - 掛載](sub-applications.md){.internal-link target=_blank}]中所述),可以像平常一樣操作,正如你所預期的那樣。 +如果你需要在同時使用具有 `root_path` 的代理時,掛載一個子應用(如[[子應用 - 掛載](sub-applications.md)]中所述),可以像平常一樣操作,正如你所預期的那樣。 FastAPI 會在內部智慧地使用 `root_path`,所以一切都能順利運作。✨ diff --git a/docs/zh-hant/docs/advanced/custom-response.md b/docs/zh-hant/docs/advanced/custom-response.md index b723aa82f6..c8355937c8 100644 --- a/docs/zh-hant/docs/advanced/custom-response.md +++ b/docs/zh-hant/docs/advanced/custom-response.md @@ -1,52 +1,36 @@ # 自訂回應——HTML、串流、檔案與其他 { #custom-response-html-stream-file-others } -預設情況下,**FastAPI** 會使用 `JSONResponse` 傳回回應。 +預設情況下,**FastAPI** 會回傳 JSON 回應。 -你可以像在[直接回傳 Response](response-directly.md){.internal-link target=_blank} 中所示,直接回傳一個 `Response` 來覆寫它。 +你可以像在[直接回傳 Response](response-directly.md)中所示,直接回傳一個 `Response` 來覆寫它。 -但如果你直接回傳一個 `Response`(或其子類別,如 `JSONResponse`),資料將不會被自動轉換(即使你宣告了 `response_model`),而且文件也不會自動產生(例如,在產生的 OpenAPI 中包含 HTTP 標頭 `Content-Type` 的特定「media type」)。 +但如果你直接回傳一個 `Response`(或其子類別,例如 `JSONResponse`),資料將不會被自動轉換(即使你宣告了 `response_model`),而且文件也不會自動產生(例如,在產生的 OpenAPI 中包含 HTTP 標頭 `Content-Type` 的特定「media type」)。 你也可以在「路徑操作裝飾器」中使用 `response_class` 參數,宣告要使用的 `Response`(例如任意 `Response` 子類別)。 你從「路徑操作函式」回傳的內容,會被放進該 `Response` 中。 -若該 `Response` 的 media type 是 JSON(`application/json`),像 `JSONResponse` 與 `UJSONResponse`,則你回傳的資料會自動以你在「路徑操作裝飾器」中宣告的 Pydantic `response_model` 進行轉換(與過濾)。 - /// note 若你使用的回應類別沒有 media type,FastAPI 會假設你的回應沒有內容,因此不會在產生的 OpenAPI 文件中記錄回應格式。 /// -## 使用 `ORJSONResponse` { #use-orjsonresponse } - -例如,若你在追求效能,你可以安裝並使用 `orjson`,並將回應設為 `ORJSONResponse`。 - -匯入你想使用的 `Response` 類別(子類),並在「路徑操作裝飾器」中宣告它。 - -對於大型回應,直接回傳 `Response` 會比回傳 `dict` 快得多。 - -這是因為預設情況下,FastAPI 會檢查每個項目並確認它能被序列化為 JSON,使用與教學中說明的相同[JSON 相容編碼器](../tutorial/encoder.md){.internal-link target=_blank}。這使你可以回傳「任意物件」,例如資料庫模型。 - -但如果你確定你回傳的內容「可以用 JSON 序列化」,你可以直接將它傳給回應類別,避免 FastAPI 在把你的回傳內容交給回應類別之前,先經過 `jsonable_encoder` 所帶來的額外開銷。 +## JSON 回應 { #json-responses } -{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} +FastAPI 預設回傳 JSON 回應。 -/// info - -參數 `response_class` 也會用來定義回應的「media type」。 +如果你宣告了[回應模型](../tutorial/response-model.md),FastAPI 會使用 Pydantic 將資料序列化為 JSON。 -在此情況下,HTTP 標頭 `Content-Type` 會被設為 `application/json`。 +如果你沒有宣告回應模型,FastAPI 會使用在[JSON 相容編碼器](../tutorial/encoder.md)中解釋的 `jsonable_encoder`,並將結果放進 `JSONResponse`。 -而且它會以此形式被記錄到 OpenAPI 中。 +如果你宣告的 `response_class` 具有 JSON 的 media type(`application/json`),像 `JSONResponse`,你回傳的資料會自動以你在「路徑操作裝飾器」中宣告的任何 Pydantic `response_model` 進行轉換(與過濾)。但資料不會由 Pydantic 直接序列化成 JSON 位元組;取而代之,會先經由 `jsonable_encoder` 轉換,然後交給 `JSONResponse` 類別,該類別會使用 Python 標準的 JSON 函式庫將其序列化為位元組。 -/// +### JSON 效能 { #json-performance } -/// tip +簡而言之,若你想要最佳效能,請使用[回應模型](../tutorial/response-model.md),並且不要在「路徑操作裝飾器」中宣告 `response_class`。 -`ORJSONResponse` 只在 FastAPI 中可用,在 Starlette 中不可用。 - -/// +{* ../../docs_src/response_model/tutorial001_01_py310.py ln[15:17] hl[16] *} ## HTML 回應 { #html-response } @@ -69,7 +53,7 @@ ### 回傳 `Response` { #return-a-response } -如[直接回傳 Response](response-directly.md){.internal-link target=_blank} 所示,你也可以在「路徑操作」中直接回傳以覆寫回應。 +如[直接回傳 Response](response-directly.md)所示,你也可以在「路徑操作」中直接回傳以覆寫回應。 上面的相同範例,回傳 `HTMLResponse`,可以像這樣: @@ -154,37 +138,11 @@ FastAPI(實際上是 Starlette)會自動包含 Content-Length 標頭。也 這是 **FastAPI** 的預設回應,如上所述。 -### `ORJSONResponse` { #orjsonresponse } - -使用 `orjson` 的快速替代 JSON 回應,如上所述。 - -/// info - -這需要安裝 `orjson`,例如使用 `pip install orjson`。 - -/// - -### `UJSONResponse` { #ujsonresponse } - -使用 `ujson` 的替代 JSON 回應。 - -/// info - -這需要安裝 `ujson`,例如使用 `pip install ujson`。 - -/// - -/// warning - -`ujson` 在處理某些邊界情況時,沒那麼嚴謹,較 Python 內建實作更「隨意」。 - -/// - -{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} +/// note | 技術細節 -/// tip +但如果你宣告了回應模型或回傳型別,將會直接用它來把資料序列化為 JSON,並直接回傳具有正確 JSON media type 的回應,而不會使用 `JSONResponse` 類別。 -`ORJSONResponse` 可能是更快的替代方案。 +這是取得最佳效能的理想方式。 /// @@ -214,31 +172,25 @@ FastAPI(實際上是 Starlette)會自動包含 Content-Length 標頭。也 ### `StreamingResponse` { #streamingresponse } -接收一個 async 產生器或一般的產生器/疊代器,並以串流方式傳送回應本文。 - -{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} - -#### 對「類檔案物件」使用 `StreamingResponse` { #using-streamingresponse-with-file-like-objects } +接收一個 async 產生器或一般的產生器/疊代器(帶有 `yield` 的函式),並以串流方式傳送回應本文。 -如果你有一個類檔案(file-like)物件(例如 `open()` 回傳的物件),你可以建立一個產生器函式來疊代該類檔案物件。 +{* ../../docs_src/custom_response/tutorial007_py310.py hl[3,16] *} -如此一來,你不必先把它全部讀進記憶體,就能將那個產生器函式傳給 `StreamingResponse` 並回傳。 - -這也包含許多用於雲端儲存、影像/影音處理等的函式庫。 +/// note | 技術細節 -{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} +一個 `async` 任務只能在抵達某個 `await` 時才能被取消。如果沒有 `await`,該產生器(帶有 `yield` 的函式)將無法被正確取消,甚至在請求取消後仍可能持續執行。 -1. 這是產生器函式。因為它內含 `yield` 陳述式,所以是「產生器函式」。 -2. 透過 `with` 區塊,我們確保在產生器函式結束後關閉類檔案物件。因此,在完成傳送回應後就會關閉。 -3. 這個 `yield from` 告訴函式去疊代名為 `file_like` 的東西。對於每個被疊代到的部分,就把該部分當作此產生器函式(`iterfile`)的輸出進行 `yield`。 +因為這個小範例不需要任何 `await` 陳述式,我們加入 `await anyio.sleep(0)`,讓事件迴圈有機會處理取消。 - 因此,這是一個把「生成」工作在內部轉交給其他東西的產生器函式。 +對於大型或無限的串流來說,這點更為重要。 - 透過這樣做,我們可以把它放進 `with` 區塊,藉此確保在完成後關閉類檔案物件。 +/// /// tip -注意,這裡我們使用的是標準的 `open()`,它不支援 `async` 與 `await`,因此我們用一般的 `def` 來宣告路徑操作。 +與其直接回傳 `StreamingResponse`,你大概會想遵循[資料串流](./stream-data.md)中的作法,這樣更方便,並且會在底層幫你處理取消。 + +如果你要串流 JSON Lines,請參考教學:[串流 JSON Lines](../tutorial/stream-json-lines.md)。 /// @@ -267,7 +219,7 @@ FastAPI(實際上是 Starlette)會自動包含 Content-Length 標頭。也 你可以建立自己的自訂回應類別,繼承自 `Response` 並加以使用。 -例如,假設你要使用 `orjson`,但想套用一些未包含在 `ORJSONResponse` 類別中的自訂設定。 +例如,假設你要使用 [`orjson`](https://github.com/ijl/orjson) 並套用一些設定。 假設你想回傳縮排且格式化的 JSON,因此要使用 orjson 選項 `orjson.OPT_INDENT_2`。 @@ -281,7 +233,7 @@ FastAPI(實際上是 Starlette)會自動包含 Content-Length 標頭。也 {"message": "Hello World"} ``` -……這個回應會回傳: +...這個回應會回傳: ```json { @@ -291,13 +243,21 @@ FastAPI(實際上是 Starlette)會自動包含 Content-Length 標頭。也 當然,你大概能找到比格式化 JSON 更好的方式來利用這個能力。😉 +### `orjson` 或回應模型 { #orjson-or-response-model } + +如果你追求效能,使用[回應模型](../tutorial/response-model.md) 大概會比使用 `orjson` 回應更好。 + +有了回應模型,FastAPI 會使用 Pydantic 直接將資料序列化為 JSON,而不需要像其他情況那樣先經過 `jsonable_encoder` 之類的中介步驟。 + +而且在底層,Pydantic 用來序列化為 JSON 的 Rust 機制和 `orjson` 相同,因此用回應模型已經能獲得最佳效能。 + ## 預設回應類別 { #default-response-class } 在建立 **FastAPI** 類別實例或 `APIRouter` 時,你可以指定預設要使用哪個回應類別。 用來設定的是 `default_response_class` 參數。 -在下面的例子中,**FastAPI** 會在所有「路徑操作」中預設使用 `ORJSONResponse`,而不是 `JSONResponse`。 +在下面的例子中,**FastAPI** 會在所有「路徑操作」中預設使用 `HTMLResponse`,而不是 JSON。 {* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} @@ -309,4 +269,4 @@ FastAPI(實際上是 Starlette)會自動包含 Content-Length 標頭。也 ## 其他文件化選項 { #additional-documentation } -你也可以在 OpenAPI 中使用 `responses` 宣告 media type 與其他許多細節:[在 OpenAPI 中的額外回應](additional-responses.md){.internal-link target=_blank}。 +你也可以在 OpenAPI 中使用 `responses` 宣告 media type 與其他許多細節:[在 OpenAPI 中的額外回應](additional-responses.md)。 diff --git a/docs/zh-hant/docs/advanced/dataclasses.md b/docs/zh-hant/docs/advanced/dataclasses.md index d586bd6844..a18b421c42 100644 --- a/docs/zh-hant/docs/advanced/dataclasses.md +++ b/docs/zh-hant/docs/advanced/dataclasses.md @@ -2,11 +2,11 @@ FastAPI 建立在 **Pydantic** 之上,我之前示範過如何使用 Pydantic 模型來宣告請求與回應。 -但 FastAPI 也同樣支援以相同方式使用 `dataclasses`: +但 FastAPI 也同樣支援以相同方式使用 [`dataclasses`](https://docs.python.org/3/library/dataclasses.html): {* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} -這之所以可行,要感謝 **Pydantic**,因為它 內建支援 `dataclasses`。 +這之所以可行,要感謝 **Pydantic**,因為它 [內建支援 `dataclasses`](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel)。 所以,即使上面的程式碼沒有明確使用 Pydantic,FastAPI 仍會使用 Pydantic 將那些標準的 dataclass 轉換為 Pydantic 版本的 dataclass。 @@ -67,7 +67,7 @@ FastAPI 建立在 **Pydantic** 之上,我之前示範過如何使用 Pydantic 一如往常,在 FastAPI 中你可以視需要混用 `def` 與 `async def`。 - 如果需要複習何時用哪個,請參考文件中關於 [`async` 與 `await`](../async.md#in-a-hurry){.internal-link target=_blank} 的章節「In a hurry?」。 + 如果需要複習何時用哪個,請參考文件中關於 [`async` 與 `await`](../async.md#in-a-hurry) 的章節「In a hurry?」。 9. 這個「路徑操作函式」回傳的不是 dataclass(雖然也可以),而是一個包含內部資料的字典清單。 FastAPI 會使用 `response_model` 參數(其中包含 dataclass)來轉換回應。 @@ -80,7 +80,7 @@ FastAPI 建立在 **Pydantic** 之上,我之前示範過如何使用 Pydantic 你也可以將 `dataclasses` 與其他 Pydantic 模型結合、從它們繼承、把它們包含進你的自訂模型等。 -想了解更多,請參考 Pydantic 關於 dataclasses 的文件。 +想了解更多,請參考 [Pydantic 關於 dataclasses 的文件](https://docs.pydantic.dev/latest/concepts/dataclasses/)。 ## 版本 { #version } diff --git a/docs/zh-hant/docs/advanced/events.md b/docs/zh-hant/docs/advanced/events.md index e5c0afe48f..7def525fa6 100644 --- a/docs/zh-hant/docs/advanced/events.md +++ b/docs/zh-hant/docs/advanced/events.md @@ -150,11 +150,11 @@ async with lifespan(app): 給有興趣鑽研的同好一點技術細節。🤓 -在底層的 ASGI 技術規範中,這屬於 Lifespan Protocol 的一部分,並定義了 `startup` 與 `shutdown` 兩種事件。 +在底層的 ASGI 技術規範中,這屬於 [Lifespan Protocol](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) 的一部分,並定義了 `startup` 與 `shutdown` 兩種事件。 /// info -你可以在 Starlette 的 Lifespan 文件 讀到更多關於 Starlette `lifespan` 處理器的資訊。 +你可以在 [Starlette 的 Lifespan 文件](https://www.starlette.dev/lifespan/) 讀到更多關於 Starlette `lifespan` 處理器的資訊。 也包含如何處理可在程式其他區域使用的 lifespan 狀態。 @@ -162,4 +162,4 @@ async with lifespan(app): ## 子應用程式 { #sub-applications } -🚨 請記住,這些生命週期事件(startup 與 shutdown)只會在主應用程式上執行,不會在[子應用程式 - 掛載](sub-applications.md){.internal-link target=_blank}上執行。 +🚨 請記住,這些生命週期事件(startup 與 shutdown)只會在主應用程式上執行,不會在[子應用程式 - 掛載](sub-applications.md)上執行。 diff --git a/docs/zh-hant/docs/advanced/generate-clients.md b/docs/zh-hant/docs/advanced/generate-clients.md index 8d374566cd..c069a8034f 100644 --- a/docs/zh-hant/docs/advanced/generate-clients.md +++ b/docs/zh-hant/docs/advanced/generate-clients.md @@ -8,11 +8,11 @@ ## 開源 SDK 產生器 { #open-source-sdk-generators } -其中一個相當萬用的選擇是 OpenAPI Generator,它支援**多種程式語言**,並能從你的 OpenAPI 規格產生 SDK。 +其中一個相當萬用的選擇是 [OpenAPI Generator](https://openapi-generator.tech/),它支援**多種程式語言**,並能從你的 OpenAPI 規格產生 SDK。 -針對 **TypeScript 用戶端**,Hey API 是專門打造的解決方案,為 TypeScript 生態系提供最佳化的體驗。 +針對 **TypeScript 用戶端**,[Hey API](https://heyapi.dev/) 是專門打造的解決方案,為 TypeScript 生態系提供最佳化的體驗。 -你可以在 OpenAPI.Tools 找到更多 SDK 產生器。 +你可以在 [OpenAPI.Tools](https://openapi.tools/#sdk) 找到更多 SDK 產生器。 /// tip @@ -24,15 +24,15 @@ FastAPI 會自動產生 **OpenAPI 3.1** 規格,因此你使用的任何工具 本節重點介紹由贊助 FastAPI 的公司提供的**創投支持**與**公司維運**的解決方案。這些產品在高品質的自動產生 SDK 之外,還提供**額外功能**與**整合**。 -透過 ✨ [**贊助 FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨,這些公司幫助確保框架與其**生態系**維持健康且**永續**。 +透過 ✨ [**贊助 FastAPI**](../help-fastapi.md#sponsor-the-author) ✨,這些公司幫助確保框架與其**生態系**維持健康且**永續**。 他們的贊助也展現對 FastAPI **社群**(你)的高度承諾,不僅關心提供**優良服務**,也支持 **FastAPI** 作為一個**穩健且蓬勃的框架**。🙇 例如,你可以嘗試: -* Speakeasy -* Stainless -* liblab +* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) +* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) +* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) 其中有些方案也可能是開源或提供免費方案,讓你不需財務承諾就能試用。其他商業的 SDK 產生器也不少,你可以在網路上找到。🤓 @@ -66,7 +66,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client 這會在 `./src/client` 產生一個 TypeScript SDK。 -你可以在他們的網站了解如何安裝 `@hey-api/openapi-ts`,以及閱讀產生的輸出內容。 +你可以在他們的網站了解如何[安裝 `@hey-api/openapi-ts`](https://heyapi.dev/openapi-ts/get-started),以及閱讀[產生的輸出內容](https://heyapi.dev/openapi-ts/output)。 ### 使用 SDK { #using-the-sdk } @@ -121,7 +121,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) ``` -……那是因為用戶端產生器對每個 *路徑操作* 都使用 OpenAPI 內部的**操作 ID(operation ID)**。 +...那是因為用戶端產生器對每個 *路徑操作* 都使用 OpenAPI 內部的**操作 ID(operation ID)**。 OpenAPI 要求每個操作 ID 在所有 *路徑操作* 之間必須唯一,因此 FastAPI 會用**函式名稱**、**路徑**與 **HTTP 方法/操作**來產生該操作 ID,如此便能確保操作 ID 的唯一性。 diff --git a/docs/zh-hant/docs/advanced/index.md b/docs/zh-hant/docs/advanced/index.md index cfbc17afec..9b1cb539ae 100644 --- a/docs/zh-hant/docs/advanced/index.md +++ b/docs/zh-hant/docs/advanced/index.md @@ -2,13 +2,13 @@ ## 更多功能 { #additional-features } -主要的[教學 - 使用者指南](../tutorial/index.md){.internal-link target=_blank} 應足以帶你快速瀏覽 **FastAPI** 的所有核心功能。 +主要的[教學 - 使用者指南](../tutorial/index.md) 應足以帶你快速瀏覽 **FastAPI** 的所有核心功能。 在接下來的章節中,你會看到其他選項、設定,以及更多功能。 /// tip -接下來的章節不一定「進階」。 +接下來的章節**不一定是「進階」**。 而且對於你的使用情境,解法很可能就在其中某一節。 @@ -16,6 +16,6 @@ ## 先閱讀教學 { #read-the-tutorial-first } -只要掌握主要[教學 - 使用者指南](../tutorial/index.md){.internal-link target=_blank} 的內容,你就能使用 **FastAPI** 的大多數功能。 +只要掌握主要[教學 - 使用者指南](../tutorial/index.md) 的內容,你就能使用 **FastAPI** 的大多數功能。 接下來的章節也假設你已經讀過,並已了解那些主要觀念。 diff --git a/docs/zh-hant/docs/advanced/middleware.md b/docs/zh-hant/docs/advanced/middleware.md index 80cda345c3..d8a53394c7 100644 --- a/docs/zh-hant/docs/advanced/middleware.md +++ b/docs/zh-hant/docs/advanced/middleware.md @@ -1,8 +1,8 @@ # 進階中介軟體 { #advanced-middleware } -在主要教學中你已學過如何將[自訂中介軟體](../tutorial/middleware.md){.internal-link target=_blank}加入到你的應用程式。 +在主要教學中你已學過如何將[自訂中介軟體](../tutorial/middleware.md)加入到你的應用程式。 -你也讀過如何使用 `CORSMiddleware` 處理 [CORS](../tutorial/cors.md){.internal-link target=_blank}。 +你也讀過如何處理 [使用 `CORSMiddleware` 的 CORS](../tutorial/cors.md)。 本節將示範如何使用其他中介軟體。 @@ -91,7 +91,7 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") 例如: -- Uvicorn 的 `ProxyHeadersMiddleware` -- MessagePack +- [Uvicorn 的 `ProxyHeadersMiddleware`](https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py) +- [MessagePack](https://github.com/florimondmanca/msgpack-asgi) -想瞭解更多可用的中介軟體,請參考 Starlette 的中介軟體文件ASGI 精選清單。 +想瞭解更多可用的中介軟體,請參考 [Starlette 的中介軟體文件](https://www.starlette.dev/middleware/) 與 [ASGI 精選清單](https://github.com/florimondmanca/awesome-asgi)。 diff --git a/docs/zh-hant/docs/advanced/openapi-callbacks.md b/docs/zh-hant/docs/advanced/openapi-callbacks.md index b1a16be249..3b01f42016 100644 --- a/docs/zh-hant/docs/advanced/openapi-callbacks.md +++ b/docs/zh-hant/docs/advanced/openapi-callbacks.md @@ -35,7 +35,7 @@ /// tip -`callback_url` 查詢參數使用的是 Pydantic 的 Url 型別。 +`callback_url` 查詢參數使用的是 Pydantic 的 [Url](https://docs.pydantic.dev/latest/api/networks/) 型別。 /// @@ -66,7 +66,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) 實際的回呼就是一個 HTTP 請求。 -當你自己實作回呼時,可以使用像是 HTTPXRequests。 +當你自己實作回呼時,可以使用像是 [HTTPX](https://www.python-httpx.org) 或 [Requests](https://requests.readthedocs.io/)。 /// @@ -106,11 +106,11 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) 和一般「路徑操作」相比有兩個主要差異: * 不需要任何實際程式碼,因為你的應用永遠不會呼叫這段程式。它只用來文件化「外部 API」。因此函式可以只有 `pass`。 -* 「路徑」可以包含一個 OpenAPI 3 表達式(見下文),可使用參數與原始送到「你的 API」的請求中的部分欄位。 +* 「路徑」可以包含一個 [OpenAPI 3 表達式](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)(見下文),可使用參數與原始送到「你的 API」的請求中的部分欄位。 ### 回呼路徑表達式 { #the-callback-path-expression } -回呼的「路徑」可以包含一個 OpenAPI 3 表達式,能引用原本送到「你的 API」的請求中的部分內容。 +回呼的「路徑」可以包含一個 [OpenAPI 3 表達式](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression),能引用原本送到「你的 API」的請求中的部分內容。 在這個例子中,它是一個 `str`: @@ -179,7 +179,7 @@ https://www.external.org/events/invoices/2expen51ve ### 檢查文件 { #check-the-docs } -現在你可以啟動應用,並前往 http://127.0.0.1:8000/docs。 +現在你可以啟動應用,並前往 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 你會在文件中看到你的「路徑操作」包含一個「Callbacks」區塊,顯示「外部 API」應該長什麼樣子: diff --git a/docs/zh-hant/docs/advanced/openapi-webhooks.md b/docs/zh-hant/docs/advanced/openapi-webhooks.md index ef52c3884f..18206c447b 100644 --- a/docs/zh-hant/docs/advanced/openapi-webhooks.md +++ b/docs/zh-hant/docs/advanced/openapi-webhooks.md @@ -48,7 +48,7 @@ Webhook 功能自 OpenAPI 3.1.0 起提供,FastAPI `0.99.0` 以上版本支援 ### 查看文件 { #check-the-docs } -現在你可以啟動應用,然後前往 http://127.0.0.1:8000/docs。 +現在你可以啟動應用,然後前往 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 你會在文件中看到一般的路徑操作,另外還有一些 webhook: diff --git a/docs/zh-hant/docs/advanced/path-operation-advanced-configuration.md b/docs/zh-hant/docs/advanced/path-operation-advanced-configuration.md index 4f25eb9878..f1607a1da5 100644 --- a/docs/zh-hant/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/zh-hant/docs/advanced/path-operation-advanced-configuration.md @@ -60,7 +60,7 @@ 你也可以宣告額外的回應及其模型、狀態碼等。 -文件中有完整章節說明,請見 [OpenAPI 中的額外回應](additional-responses.md){.internal-link target=_blank}。 +文件中有完整章節說明,請見 [OpenAPI 中的額外回應](additional-responses.md)。 ## OpenAPI 額外資訊 { #openapi-extra } @@ -68,7 +68,7 @@ /// note | 技術細節 -在 OpenAPI 規格中,這稱為 Operation 物件。 +在 OpenAPI 規格中,這稱為 [Operation 物件](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object)。 /// @@ -82,7 +82,7 @@ 這是一個較低階的擴充介面。 -如果你只需要宣告額外回應,更方便的方式是使用 [OpenAPI 中的額外回應](additional-responses.md){.internal-link target=_blank}。 +如果你只需要宣告額外回應,更方便的方式是使用 [OpenAPI 中的額外回應](additional-responses.md)。 /// diff --git a/docs/zh-hant/docs/advanced/response-change-status-code.md b/docs/zh-hant/docs/advanced/response-change-status-code.md index 4b8d459ca2..31b688512e 100644 --- a/docs/zh-hant/docs/advanced/response-change-status-code.md +++ b/docs/zh-hant/docs/advanced/response-change-status-code.md @@ -1,6 +1,6 @@ # 回應 - 變更狀態碼 { #response-change-status-code } -你可能已經讀過,可以設定預設的[回應狀態碼](../tutorial/response-status-code.md){.internal-link target=_blank}。 +你可能已經讀過,可以設定預設的[回應狀態碼](../tutorial/response-status-code.md)。 但有些情況你需要回傳與預設不同的狀態碼。 @@ -26,6 +26,6 @@ 若你宣告了 `response_model`,它仍會被用來過濾並轉換你回傳的物件。 -FastAPI 會使用那個「*暫時的*」回應來取得狀態碼(以及 Cookies 和標頭),並將它們放入最終回應中;最終回應包含你回傳的值,且會被任何 `response_model` 過濾。 +**FastAPI** 會使用那個「*暫時的*」回應來取得狀態碼(以及 Cookies 和標頭),並將它們放入最終回應中;最終回應包含你回傳的值,且會被任何 `response_model` 過濾。 你也可以在相依性(dependencies)中宣告 `Response` 參數,並在其中設定狀態碼。但請注意,最後被設定的值會生效。 diff --git a/docs/zh-hant/docs/advanced/response-cookies.md b/docs/zh-hant/docs/advanced/response-cookies.md index b7225d571c..2ba14c3f6f 100644 --- a/docs/zh-hant/docs/advanced/response-cookies.md +++ b/docs/zh-hant/docs/advanced/response-cookies.md @@ -20,7 +20,7 @@ FastAPI 會使用那個暫時的 `Response` 取出 Cookie(以及標頭與狀 當你在程式碼中直接回傳 `Response` 時,也可以建立 Cookie。 -要這麼做,你可以依照 [直接回傳 Response](response-directly.md){.internal-link target=_blank} 中的說明建立一個回應。 +要這麼做,你可以依照 [直接回傳 Response](response-directly.md) 中的說明建立一個回應。 接著在其中設定 Cookie,然後回傳它: @@ -48,4 +48,4 @@ FastAPI 會使用那個暫時的 `Response` 取出 Cookie(以及標頭與狀 /// -想查看所有可用的參數與選項,請參閱 Starlette 文件。 +想查看所有可用的參數與選項,請參閱 [Starlette 文件](https://www.starlette.dev/responses/#set-cookie)。 diff --git a/docs/zh-hant/docs/advanced/response-directly.md b/docs/zh-hant/docs/advanced/response-directly.md index 5603548934..16face2612 100644 --- a/docs/zh-hant/docs/advanced/response-directly.md +++ b/docs/zh-hant/docs/advanced/response-directly.md @@ -2,19 +2,23 @@ 當你建立一個 **FastAPI** 的路徑操作 (path operation) 時,通常可以從中回傳任何資料:`dict`、`list`、Pydantic 模型、資料庫模型等。 -預設情況下,**FastAPI** 會使用在[JSON 相容編碼器](../tutorial/encoder.md){.internal-link target=_blank}中說明的 `jsonable_encoder`,自動將回傳值轉為 JSON。 +如果你宣告了 [回應模型](../tutorial/response-model.md),FastAPI 會用 Pydantic 將資料序列化為 JSON。 -然後在幕後,它會把這些與 JSON 相容的資料(例如 `dict`)放進 `JSONResponse`,用來把回應傳回給用戶端。 +如果你沒有宣告回應模型,FastAPI 會使用在[JSON 相容編碼器](../tutorial/encoder.md)中說明的 `jsonable_encoder`,並把它放進 `JSONResponse`。 但你也可以直接從路徑操作回傳 `JSONResponse`。 -例如,當你需要回傳自訂的 headers 或 cookies 時就很有用。 +/// tip + +通常使用 [回應模型](../tutorial/response-model.md) 會有更好的效能,因為那樣會在 Rust 端使用 Pydantic 來序列化資料,而不是直接回傳 `JSONResponse`。 + +/// ## 回傳 `Response` { #return-a-response } 其實,你可以回傳任何 `Response`,或其任何子類別。 -/// tip +/// info `JSONResponse` 本身就是 `Response` 的子類別。 @@ -26,6 +30,8 @@ 這給了你很大的彈性。你可以回傳任何資料型別、覆寫任何資料宣告或驗證等。 +同時也帶來了很大的責任。你必須確保你回傳的資料是正確的、格式正確、可被序列化等。 + ## 在 `Response` 中使用 `jsonable_encoder` { #using-the-jsonable-encoder-in-a-response } 因為 **FastAPI** 不會對你回傳的 `Response` 做任何更動,你需要自行確保它的內容已經準備好。 @@ -50,16 +56,28 @@ 現在來看看如何用它來回傳自訂回應。 -假設你想要回傳一個 XML 回應。 +假設你想要回傳一個 [XML](https://en.wikipedia.org/wiki/XML) 回應。 你可以把 XML 內容放進一個字串,把它放進 `Response`,然後回傳它: {* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} +## 回應模型如何運作 { #how-a-response-model-works } + +當你在路徑操作中宣告 [回應模型 - 回傳型別](../tutorial/response-model.md) 時,**FastAPI** 會用 Pydantic 將資料序列化為 JSON。 + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +由於這會在 Rust 端發生,效能會比用一般的 Python 與 `JSONResponse` 類別來完成好得多。 + +當使用 `response_model` 或回傳型別時,FastAPI 不會使用 `jsonable_encoder` 來轉換資料(那會較慢),也不會使用 `JSONResponse` 類別。 + +相反地,它會取用用回應模型(或回傳型別)透過 Pydantic 產生的 JSON 位元組,並直接回傳具備正確 JSON 媒體型別(`application/json`)的 `Response`。 + ## 注意事項 { #notes } 當你直接回傳 `Response` 時,其資料不會自動被驗證、轉換(序列化)或文件化。 -但你仍然可以依照[在 OpenAPI 中的額外回應](additional-responses.md){.internal-link target=_blank}中的說明進行文件化。 +但你仍然可以依照[在 OpenAPI 中的額外回應](additional-responses.md)中的說明進行文件化。 在後續章節中,你會看到如何在仍保有自動資料轉換、文件化等的同時,使用/宣告這些自訂的 `Response`。 diff --git a/docs/zh-hant/docs/advanced/response-headers.md b/docs/zh-hant/docs/advanced/response-headers.md index 6e32ca1b39..4f7494a8b3 100644 --- a/docs/zh-hant/docs/advanced/response-headers.md +++ b/docs/zh-hant/docs/advanced/response-headers.md @@ -20,7 +20,7 @@ FastAPI 會使用那個暫時性的回應來擷取標頭(還有 Cookie 與狀 當你直接回傳 `Response` 時,也能加入標頭。 -依照[直接回傳 Response](response-directly.md){.internal-link target=_blank}中的說明建立回應,並把標頭作為額外參數傳入: +依照[直接回傳 Response](response-directly.md)中的說明建立回應,並把標頭作為額外參數傳入: {* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} @@ -36,6 +36,6 @@ FastAPI 會使用那個暫時性的回應來擷取標頭(還有 Cookie 與狀 ## 自訂標頭 { #custom-headers } -請記住,專有的自訂標頭可以使用 `X-` 前綴來新增。 +請記住,專有的自訂標頭可以[使用 `X-` 前綴](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)來新增。 -但如果你有自訂標頭並希望瀏覽器端的客戶端能看見它們,你需要把這些標頭加入到 CORS 設定中(詳見 [CORS(跨來源資源共用)](../tutorial/cors.md){.internal-link target=_blank}),使用在Starlette 的 CORS 文件中記載的 `expose_headers` 參數。 +但如果你有自訂標頭並希望瀏覽器端的客戶端能看見它們,你需要把這些標頭加入到 CORS 設定中(詳見 [CORS(跨來源資源共用)](../tutorial/cors.md)),使用在[Starlette 的 CORS 文件](https://www.starlette.dev/middleware/#corsmiddleware)中記載的 `expose_headers` 參數。 diff --git a/docs/zh-hant/docs/advanced/security/http-basic-auth.md b/docs/zh-hant/docs/advanced/security/http-basic-auth.md index ea3d528292..817cf166b9 100644 --- a/docs/zh-hant/docs/advanced/security/http-basic-auth.md +++ b/docs/zh-hant/docs/advanced/security/http-basic-auth.md @@ -32,7 +32,7 @@ 使用一個依賴來檢查使用者名稱與密碼是否正確。 -為此,使用 Python 標準模組 `secrets` 來比對使用者名稱與密碼。 +為此,使用 Python 標準模組 [`secrets`](https://docs.python.org/3/library/secrets.html) 來比對使用者名稱與密碼。 `secrets.compare_digest()` 需要接收 `bytes`,或是只包含 ASCII 字元(英文字符)的 `str`。這表示它無法處理像 `á` 這樣的字元,例如 `Sebastián`。 diff --git a/docs/zh-hant/docs/advanced/security/index.md b/docs/zh-hant/docs/advanced/security/index.md index 9a4cfbbfd6..9ddf356756 100644 --- a/docs/zh-hant/docs/advanced/security/index.md +++ b/docs/zh-hant/docs/advanced/security/index.md @@ -2,11 +2,11 @@ ## 額外功能 { #additional-features } -除了[教學 - 使用者指南:安全性](../../tutorial/security/index.md){.internal-link target=_blank}中涵蓋的內容外,還有一些用來處理安全性的額外功能。 +除了[教學 - 使用者指南:安全性](../../tutorial/security/index.md)中涵蓋的內容外,還有一些用來處理安全性的額外功能。 /// tip -以下各節不一定是「進階」內容。 +以下各節**不一定是「進階」**內容。 而且你的情境很可能可以在其中找到解決方案。 @@ -14,6 +14,6 @@ ## 請先閱讀教學 { #read-the-tutorial-first } -以下各節假設你已閱讀主要的[教學 - 使用者指南:安全性](../../tutorial/security/index.md){.internal-link target=_blank}。 +以下各節假設你已閱讀主要的[教學 - 使用者指南:安全性](../../tutorial/security/index.md)。 它們都建立在相同的概念之上,但提供一些額外的功能。 diff --git a/docs/zh-hant/docs/advanced/security/oauth2-scopes.md b/docs/zh-hant/docs/advanced/security/oauth2-scopes.md index 029572d433..05088be7ed 100644 --- a/docs/zh-hant/docs/advanced/security/oauth2-scopes.md +++ b/docs/zh-hant/docs/advanced/security/oauth2-scopes.md @@ -60,7 +60,7 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 ## 全局概觀 { #global-view } -先快速看看相對於主教學「使用密碼(與雜湊)、Bearer 與 JWT token 的 OAuth2」的差異([OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank})。現在加入了 OAuth2 scopes: +先快速看看相對於主教學「使用密碼(與雜湊)、Bearer 與 JWT token 的 OAuth2」的差異([OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md))。現在加入了 OAuth2 scopes: {* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} @@ -271,4 +271,4 @@ FastAPI 在 `fastapi.security.oauth2` 中提供了所有這些 OAuth2 驗證流 ## 在裝飾器 `dependencies` 中使用 `Security` { #security-in-decorator-dependencies } -就像你可以在裝飾器的 `dependencies` 參數中定義一個 `Depends` 的 `list` 一樣(詳見[路徑操作裝飾器中的相依性](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}),你也可以在那裡使用帶有 `scopes` 的 `Security`。 +就像你可以在裝飾器的 `dependencies` 參數中定義一個 `Depends` 的 `list` 一樣(詳見[路徑操作裝飾器中的相依性](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md)),你也可以在那裡使用帶有 `scopes` 的 `Security`。 diff --git a/docs/zh-hant/docs/advanced/settings.md b/docs/zh-hant/docs/advanced/settings.md index 1ee5ad7cc2..9892f8f000 100644 --- a/docs/zh-hant/docs/advanced/settings.md +++ b/docs/zh-hant/docs/advanced/settings.md @@ -8,7 +8,7 @@ /// tip -若想了解環境變數,你可以閱讀[環境變數](../environment-variables.md){.internal-link target=_blank}。 +若想了解環境變數,你可以閱讀[環境變數](../environment-variables.md)。 /// @@ -20,11 +20,11 @@ ## Pydantic `Settings` { #pydantic-settings } -幸好,Pydantic 提供了很好的工具,可用來處理由環境變數而來的設定:Pydantic:設定管理。 +幸好,Pydantic 提供了很好的工具,可用來處理由環境變數而來的設定:[Pydantic:設定管理](https://docs.pydantic.dev/latest/concepts/pydantic_settings/)。 ### 安裝 `pydantic-settings` { #install-pydantic-settings } -首先,請先建立你的[虛擬環境](../virtual-environments.md){.internal-link target=_blank},啟用它,然後安裝 `pydantic-settings` 套件: +首先,請先建立你的[虛擬環境](../virtual-environments.md),啟用它,然後安裝 `pydantic-settings` 套件:
@@ -100,7 +100,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p ## 在另一個模組中的設定 { #settings-in-another-module } -你也可以把這些設定放在另一個模組檔案中,就像在[更大的應用程式 - 多個檔案](../tutorial/bigger-applications.md){.internal-link target=_blank}所示。 +你也可以把這些設定放在另一個模組檔案中,就像在[更大的應用程式 - 多個檔案](../tutorial/bigger-applications.md)所示。 例如,你可以有一個 `config.py` 檔案如下: @@ -112,7 +112,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p /// tip -你也需要一個 `__init__.py` 檔案,詳見[更大的應用程式 - 多個檔案](../tutorial/bigger-applications.md){.internal-link target=_blank}。 +你也需要一個 `__init__.py` 檔案,詳見[更大的應用程式 - 多個檔案](../tutorial/bigger-applications.md)。 /// @@ -172,7 +172,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p /// -Pydantic 透過外部函式庫支援讀取這類型的檔案。你可以閱讀更多:Pydantic Settings:Dotenv (.env) 支援。 +Pydantic 透過外部函式庫支援讀取這類型的檔案。你可以閱讀更多:[Pydantic Settings:Dotenv (.env) 支援](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support)。 /// tip @@ -197,7 +197,7 @@ APP_NAME="ChimichangApp" /// tip -`model_config` 屬性僅用於 Pydantic 的設定。你可以閱讀更多:Pydantic:概念:設定。 +`model_config` 屬性僅用於 Pydantic 的設定。你可以閱讀更多:[Pydantic:概念:設定](https://docs.pydantic.dev/latest/concepts/config/)。 /// @@ -291,7 +291,7 @@ participant execute as Execute function 如此一來,它的行為幾乎就像全域變數。但因為它使用相依函式,因此我們可以在測試時輕鬆將其覆寫。 -`@lru_cache` 是 `functools` 的一部分,而 `functools` 是 Python 標準程式庫的一部分。你可以在Python 文件中閱讀 `@lru_cache` 以了解更多。 +`@lru_cache` 是 `functools` 的一部分,而 `functools` 是 Python 標準程式庫的一部分。你可以在[Python 文件中閱讀 `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache) 以了解更多。 ## 回顧 { #recap } diff --git a/docs/zh-hant/docs/advanced/sub-applications.md b/docs/zh-hant/docs/advanced/sub-applications.md index 773bc4b886..7199e6d629 100644 --- a/docs/zh-hant/docs/advanced/sub-applications.md +++ b/docs/zh-hant/docs/advanced/sub-applications.md @@ -30,25 +30,25 @@ ### 檢查自動 API 文件 { #check-the-automatic-api-docs } -現在,用你的檔案執行 `fastapi` 指令: +現在,執行 `fastapi` 指令:
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-然後開啟位於 http://127.0.0.1:8000/docs 的文件。 +然後開啟位於 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) 的文件。 你會看到主應用的自動 API 文件,只包含它自己的*路徑操作*: -接著,開啟子應用程式的文件:http://127.0.0.1:8000/subapi/docs。 +接著,開啟子應用程式的文件:[http://127.0.0.1:8000/subapi/docs](http://127.0.0.1:8000/subapi/docs)。 你會看到子應用程式的自動 API 文件,只包含它自己的*路徑操作*,而且都在正確的子路徑前綴 `/subapi` 之下: @@ -64,4 +64,4 @@ $ fastapi dev main.py 而且子應用程式也能再掛載自己的子應用程式,一切都能正確運作,因為 FastAPI 會自動處理所有這些 `root_path`。 -你可以在[在代理伺服器之後](behind-a-proxy.md){.internal-link target=_blank}一節中進一步了解 `root_path` 與如何顯式使用它。 +你可以在[在代理伺服器之後](behind-a-proxy.md)一節中進一步了解 `root_path` 與如何顯式使用它。 diff --git a/docs/zh-hant/docs/advanced/templates.md b/docs/zh-hant/docs/advanced/templates.md index ffc7599ae2..6e622d5a77 100644 --- a/docs/zh-hant/docs/advanced/templates.md +++ b/docs/zh-hant/docs/advanced/templates.md @@ -8,7 +8,7 @@ ## 安裝相依套件 { #install-dependencies } -請先建立一個[虛擬環境](../virtual-environments.md){.internal-link target=_blank}、啟用它,然後安裝 `jinja2`: +請先建立一個[虛擬環境](../virtual-environments.md)、啟用它,然後安裝 `jinja2`:
@@ -123,4 +123,4 @@ Item ID: 42 ## 更多細節 { #more-details } -想了解更多細節(包含如何測試模板),請參考 Starlette 的模板說明文件。 +想了解更多細節(包含如何測試模板),請參考 [Starlette 的模板說明文件](https://www.starlette.dev/templates/)。 diff --git a/docs/zh-hant/docs/advanced/testing-websockets.md b/docs/zh-hant/docs/advanced/testing-websockets.md index 7348e60fdf..caedc11dbd 100644 --- a/docs/zh-hant/docs/advanced/testing-websockets.md +++ b/docs/zh-hant/docs/advanced/testing-websockets.md @@ -8,6 +8,6 @@ /// note | 注意 -想了解更多,請參考 Starlette 的 測試 WebSocket 文件。 +想了解更多,請參考 Starlette 的[測試 WebSocket](https://www.starlette.dev/testclient/#testing-websocket-sessions)文件。 /// diff --git a/docs/zh-hant/docs/advanced/using-request-directly.md b/docs/zh-hant/docs/advanced/using-request-directly.md index f1dae9bf29..2c355982de 100644 --- a/docs/zh-hant/docs/advanced/using-request-directly.md +++ b/docs/zh-hant/docs/advanced/using-request-directly.md @@ -15,7 +15,7 @@ ## 關於 `Request` 物件的細節 { #details-about-the-request-object } -由於 FastAPI 底層其實是 Starlette,再加上一層工具,因此在需要時你可以直接使用 Starlette 的 `Request` 物件。 +由於 FastAPI 底層其實是 Starlette,再加上一層工具,因此在需要時你可以直接使用 Starlette 的 [`Request`](https://www.starlette.dev/requests/) 物件。 同時也代表,如果你直接從 `Request` 物件取得資料(例如讀取 body),FastAPI 不會替它做驗證、轉換或文件化(透過 OpenAPI 為自動化的 API 介面產生文件)。 @@ -45,7 +45,7 @@ ## `Request` 文件 { #request-documentation } -你可以在 Starlette 官方文件站點中的 `Request` 物件 了解更多細節。 +你可以在 [Starlette 官方文件站點中的 `Request` 物件](https://www.starlette.dev/requests/) 了解更多細節。 /// note | 技術細節 diff --git a/docs/zh-hant/docs/advanced/websockets.md b/docs/zh-hant/docs/advanced/websockets.md index 22e3fdcb9e..57f51bcfbe 100644 --- a/docs/zh-hant/docs/advanced/websockets.md +++ b/docs/zh-hant/docs/advanced/websockets.md @@ -1,10 +1,10 @@ # WebSockets { #websockets } -你可以在 **FastAPI** 中使用 WebSockets。 +你可以在 **FastAPI** 中使用 [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)。 ## 安裝 `websockets` { #install-websockets } -請先建立[虛擬環境](../virtual-environments.md){.internal-link target=_blank}、啟用它,然後安裝 `websockets`(一個讓你更容易使用「WebSocket」通訊協定的 Python 套件): +請先建立[虛擬環境](../virtual-environments.md)、啟用它,然後安裝 `websockets`(一個讓你更容易使用「WebSocket」通訊協定的 Python 套件):
@@ -69,14 +69,14 @@ $ pip install websockets
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-在瀏覽器開啟 http://127.0.0.1:8000。 +在瀏覽器開啟 [http://127.0.0.1:8000](http://127.0.0.1:8000)。 你會看到一個像這樣的簡單頁面: @@ -115,25 +115,25 @@ $ fastapi dev main.py 因為這是 WebSocket,拋出 `HTTPException` 並沒有意義,因此我們改為拋出 `WebSocketException`。 -你可以使用規範中定義的有效關閉代碼之一。 +你可以使用規範中定義的[有效關閉代碼](https://tools.ietf.org/html/rfc6455#section-7.4.1)之一。 /// ### 用依賴試用 WebSocket { #try-the-websockets-with-dependencies } -如果你的檔案名為 `main.py`,用以下指令執行應用: +執行你的應用:
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-在瀏覽器開啟 http://127.0.0.1:8000。 +在瀏覽器開啟 [http://127.0.0.1:8000](http://127.0.0.1:8000)。 在那裡你可以設定: @@ -174,7 +174,7 @@ Client #1596980209979 left the chat 但請注意,因為所有狀態都在記憶體中的單一 list 裡管理,它只會在該程序執行期間生效,且僅適用於單一程序。 -如果你需要一個容易與 FastAPI 整合、但更健壯,且可由 Redis、PostgreSQL 等後端支援的方案,請參考 encode/broadcaster。 +如果你需要一個容易與 FastAPI 整合、但更健壯,且可由 Redis、PostgreSQL 等後端支援的方案,請參考 [encode/broadcaster](https://github.com/encode/broadcaster)。 /// @@ -182,5 +182,5 @@ Client #1596980209979 left the chat 想了解更多選項,請參考 Starlette 的文件: -* `WebSocket` 類別。 -* 以類別為基礎的 WebSocket 處理。 +* [`WebSocket` 類別](https://www.starlette.dev/websockets/)。 +* [以類別為基礎的 WebSocket 處理](https://www.starlette.dev/endpoints/#websocketendpoint)。 diff --git a/docs/zh-hant/docs/advanced/wsgi.md b/docs/zh-hant/docs/advanced/wsgi.md index 9d03b56924..c1baff34ed 100644 --- a/docs/zh-hant/docs/advanced/wsgi.md +++ b/docs/zh-hant/docs/advanced/wsgi.md @@ -1,6 +1,6 @@ # 包含 WSGI:Flask、Django 等 { #including-wsgi-flask-django-others } -你可以像在 [子應用程式 - 掛載](sub-applications.md){.internal-link target=_blank}、[在 Proxy 後方](behind-a-proxy.md){.internal-link target=_blank} 中所見那樣掛載 WSGI 應用。 +你可以像在 [子應用程式 - 掛載](sub-applications.md)、[在 Proxy 後方](behind-a-proxy.md) 中所見那樣掛載 WSGI 應用。 為此,你可以使用 `WSGIMiddleware` 來包住你的 WSGI 應用,例如 Flask、Django 等。 @@ -36,13 +36,13 @@ 其餘則由 **FastAPI** 處理。 -如果你啟動它並前往 http://localhost:8000/v1/,你會看到來自 Flask 的回應: +如果你啟動它並前往 [http://localhost:8000/v1/](http://localhost:8000/v1/),你會看到來自 Flask 的回應: ```txt Hello, World from Flask! ``` -如果你前往 http://localhost:8000/v2,你會看到來自 FastAPI 的回應: +如果你前往 [http://localhost:8000/v2](http://localhost:8000/v2),你會看到來自 FastAPI 的回應: ```JSON { diff --git a/docs/zh-hant/docs/alternatives.md b/docs/zh-hant/docs/alternatives.md index 340c47d8ba..ee99faf99f 100644 --- a/docs/zh-hant/docs/alternatives.md +++ b/docs/zh-hant/docs/alternatives.md @@ -14,7 +14,7 @@ ## 先前的工具 { #previous-tools } -### Django { #django } +### [Django](https://www.djangoproject.com/) { #django } 它是最受歡迎且廣受信任的 Python 框架。像 Instagram 等系統就是用它打造的。 @@ -22,7 +22,7 @@ 它一開始是為在後端產生 HTML 而設計,而非為了建立提供現代前端(如 React、Vue.js、Angular)或其他系統(如 IoT 裝置)使用的 API。 -### Django REST Framework { #django-rest-framework } +### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } Django REST framework 的目標是成為一套在 Django 之上構建 Web API 的彈性工具組,以強化其 API 能力。 @@ -30,7 +30,7 @@ Django REST framework 的目標是成為一套在 Django 之上構建 Web API 它是「自動 API 文件」的早期典範之一,而這正是啟發我「尋找」**FastAPI** 的第一個想法。 -/// note | 注意 +/// note Django REST Framework 由 Tom Christie 創建。他同時也是 Starlette 與 Uvicorn 的作者,而 **FastAPI** 就是建立在它們之上。 @@ -42,7 +42,7 @@ Django REST Framework 由 Tom Christie 創建。他同時也是 Starlette 與 Uv /// -### Flask { #flask } +### [Flask](https://flask.palletsprojects.com) { #flask } Flask 是一個「微框架」,它不包含資料庫整合,也沒有像 Django 那樣內建許多功能。 @@ -64,7 +64,7 @@ Flask 是一個「微框架」,它不包含資料庫整合,也沒有像 Djan /// -### Requests { #requests } +### [Requests](https://requests.readthedocs.io) { #requests } **FastAPI** 其實不是 **Requests** 的替代品。兩者的範疇截然不同。 @@ -106,7 +106,7 @@ def read_url(): /// -### Swagger / OpenAPI { #swagger-openapi } +### [Swagger](https://swagger.io/) / [OpenAPI](https://github.com/OAI/OpenAPI-Specification/) { #swagger-openapi } 我想從 Django REST Framework 得到的主要功能是自動 API 文件。 @@ -124,8 +124,8 @@ def read_url(): 並整合基於標準的使用者介面工具: -* Swagger UI -* ReDoc +* [Swagger UI](https://github.com/swagger-api/swagger-ui) +* [ReDoc](https://github.com/Rebilly/ReDoc) 選擇這兩個是因為它們相當受歡迎且穩定,但稍加搜尋,你會發現有數十種 OpenAPI 的替代使用者介面(都能與 **FastAPI** 一起使用)。 @@ -135,7 +135,7 @@ def read_url(): 有幾個 Flask 的 REST 框架,但在投入時間調查後,我發現許多已停止維護或被棄置,且存在一些關鍵問題使之不適用。 -### Marshmallow { #marshmallow } +### [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) { #marshmallow } API 系統需要的主要功能之一是資料「序列化」,也就是把程式中的資料(Python)轉成能透過網路傳輸的形式。例如,將含有資料庫資料的物件轉成 JSON 物件、把 `datetime` 物件轉成字串等等。 @@ -153,7 +153,7 @@ API 需要的另一個重要功能是資料驗證,確保資料在特定條件 /// -### Webargs { #webargs } +### [Webargs](https://webargs.readthedocs.io/en/latest/) { #webargs } API 所需的另一項大功能,是從傳入請求中解析資料。 @@ -175,7 +175,7 @@ Webargs 由與 Marshmallow 相同的開發者創建。 /// -### APISpec { #apispec } +### [APISpec](https://apispec.readthedocs.io/en/stable/) { #apispec } Marshmallow 與 Webargs 以外掛提供驗證、解析與序列化。 @@ -205,7 +205,7 @@ APISpec 由與 Marshmallow 相同的開發者創建。 /// -### Flask-apispec { #flask-apispec } +### [Flask-apispec](https://flask-apispec.readthedocs.io/en/latest/) { #flask-apispec } 這是一個 Flask 外掛,把 Webargs、Marshmallow 與 APISpec 串在一起。 @@ -219,11 +219,11 @@ APISpec 由與 Marshmallow 相同的開發者創建。 使用它促成了數個 Flask 全端(full-stack)產生器。這些是我(以及若干外部團隊)至今主要使用的技術組合: -* https://github.com/tiangolo/full-stack -* https://github.com/tiangolo/full-stack-flask-couchbase -* https://github.com/tiangolo/full-stack-flask-couchdb +* [https://github.com/tiangolo/full-stack](https://github.com/tiangolo/full-stack) +* [https://github.com/tiangolo/full-stack-flask-couchbase](https://github.com/tiangolo/full-stack-flask-couchbase) +* [https://github.com/tiangolo/full-stack-flask-couchdb](https://github.com/tiangolo/full-stack-flask-couchdb) -而這些全端產生器,也成為了 [**FastAPI** 專案產生器](project-generation.md){.internal-link target=_blank} 的基礎。 +而這些全端產生器,也成為了 [**FastAPI** 專案產生器](project-generation.md) 的基礎。 /// info @@ -237,7 +237,7 @@ Flask-apispec 由與 Marshmallow 相同的開發者創建。 /// -### NestJS(與 Angular) { #nestjs-and-angular } +### [NestJS](https://nestjs.com/)(與 [Angular](https://angular.io/)) { #nestjs-and-angular } 這甚至不是 Python。NestJS 是受 Angular 啟發的 JavaScript(TypeScript)NodeJS 框架。 @@ -259,13 +259,13 @@ Flask-apispec 由與 Marshmallow 相同的開發者創建。 /// -### Sanic { #sanic } +### [Sanic](https://sanic.readthedocs.io/en/latest/) { #sanic } 它是最早基於 `asyncio` 的極高速 Python 框架之一,並做得很像 Flask。 /// note | 技術細節 -它使用 `uvloop` 取代預設的 Python `asyncio` 事件圈。這也是它如此之快的原因。 +它使用 [`uvloop`](https://github.com/MagicStack/uvloop) 取代預設的 Python `asyncio` 事件圈。這也是它如此之快的原因。 它明顯啟發了 Uvicorn 與 Starlette,而在公開的基準測試中,它們目前比 Sanic 更快。 @@ -279,7 +279,7 @@ Flask-apispec 由與 Marshmallow 相同的開發者創建。 /// -### Falcon { #falcon } +### [Falcon](https://falconframework.org/) { #falcon } Falcon 是另一個高效能 Python 框架,設計上極簡,並作為其他框架(如 Hug)的基礎。 @@ -297,7 +297,7 @@ Falcon 是另一個高效能 Python 框架,設計上極簡,並作為其他 /// -### Molten { #molten } +### [Molten](https://moltenframework.com/) { #molten } 我在 **FastAPI** 打造的早期發現了 Molten。它有一些相當類似的想法: @@ -321,7 +321,7 @@ Falcon 是另一個高效能 Python 框架,設計上極簡,並作為其他 /// -### Hug { #hug } +### [Hug](https://github.com/hugapi/hug) { #hug } Hug 是最早使用 Python 型別提示來宣告 API 參數型別的框架之一。這是個很棒的點子,也啟發了其他工具。 @@ -337,7 +337,7 @@ Hug 是最早使用 Python 型別提示來宣告 API 參數型別的框架之一 /// info -Hug 由 Timothy Crosley 創建,他同時也是 `isort` 的作者,一個自動排序 Python 匯入的好工具。 +Hug 由 Timothy Crosley 創建,他同時也是 [`isort`](https://github.com/timothycrosley/isort) 的作者,一個自動排序 Python 匯入的好工具。 /// @@ -351,7 +351,7 @@ Hug 啟發 **FastAPI** 在函式中宣告 `response` 參數以設定標頭與 Co /// -### APIStar (<= 0.5) { #apistar-0-5 } +### [APIStar](https://github.com/encode/apistar) (<= 0.5) { #apistar-0-5 } 在決定打造 **FastAPI** 之前,我找到了 **APIStar** 伺服器。它幾乎具備我所尋找的一切,而且設計很出色。 @@ -401,7 +401,7 @@ APIStar 由 Tom Christie 創建。他也創建了: ## **FastAPI** 所採用的工具 { #used-by-fastapi } -### Pydantic { #pydantic } +### [Pydantic](https://docs.pydantic.dev/) { #pydantic } Pydantic 是基於 Python 型別提示,定義資料驗證、序列化與文件(使用 JSON Schema)的函式庫。 @@ -417,7 +417,7 @@ Pydantic 是基於 Python 型別提示,定義資料驗證、序列化與文件 /// -### Starlette { #starlette } +### [Starlette](https://www.starlette.dev/) { #starlette } Starlette 是一個輕量的 ASGI 框架/工具集,非常適合用來建構高效能的 asyncio 服務。 @@ -458,11 +458,11 @@ ASGI 是由 Django 核心團隊成員正在開發的新「標準」。它尚未 `FastAPI` 這個類別本身直接繼承自 `Starlette` 類別。 -因此,凡是你能用 Starlette 做的事,你幾乎都能直接用 **FastAPI** 完成,因為它基本上就是加強版的 Starlette。 +因此,凡是你能用 Starlette 做的事,你都能直接用 **FastAPI** 完成,因為它基本上就是加強版的 Starlette。 /// -### Uvicorn { #uvicorn } +### [Uvicorn](https://www.uvicorn.dev/) { #uvicorn } Uvicorn 是基於 uvloop 與 httptools 的極速 ASGI 伺服器。 @@ -476,10 +476,10 @@ Uvicorn 是基於 uvloop 與 httptools 的極速 ASGI 伺服器。 你也可以使用 `--workers` 命令列選項,取得非同步的多製程伺服器。 -更多細節請見[部署](deployment/index.md){.internal-link target=_blank}章節。 +更多細節請見[部署](deployment/index.md)章節。 /// ## 效能與速度 { #benchmarks-and-speed } -想了解、比較並看出 Uvicorn、Starlette 與 FastAPI 之間的差異,請參考[效能評測](benchmarks.md){.internal-link target=_blank}。 +想了解、比較並看出 Uvicorn、Starlette 與 FastAPI 之間的差異,請參考[效能評測](benchmarks.md)。 diff --git a/docs/zh-hant/docs/async.md b/docs/zh-hant/docs/async.md index a03d71815f..9a08938ca5 100644 --- a/docs/zh-hant/docs/async.md +++ b/docs/zh-hant/docs/async.md @@ -141,7 +141,7 @@ def results(): /// info -漂亮的插畫來自 Ketrina Thompson. 🎨 +漂亮的插畫來自 [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot)。 🎨 /// @@ -207,7 +207,7 @@ def results(): /// info -漂亮的插畫來自 Ketrina Thompson. 🎨 +漂亮的插畫來自 [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot)。 🎨 /// @@ -245,13 +245,13 @@ def results(): 這種「等待」 🕙 通常以微秒來衡量,但累加起來,最終還是花費了很多等待時間。 -這就是為什麼對於 Web API 來說,使用非同步程式碼 ⏸🔀⏯ 是非常有意義的。 +這就是為什麼對於 Web API 來說,使用非同步程式碼 ⏸🔀⏯ 是非常有意味的。 這種類型的非同步性正是 NodeJS 成功的原因(儘管 NodeJS 不是平行的),這也是 Go 語言作為程式語言的一個強大優勢。 這與 **FastAPI** 所能提供的性能水平相同。 -你可以同時利用並行性和平行性,進一步提升效能,這比大多數已測試的 NodeJS 框架都更快,並且與 Go 語言相當,而 Go 是一種更接近 C 的編譯語言(感謝 Starlette)。 +你可以同時利用並行性和平行性,進一步提升效能,這比大多數已測試的 NodeJS 框架都更快,並且與 Go 語言相當,而 Go 是一種更接近 C 的編譯語言([感謝 Starlette](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1))。 ### 並行比平行更好嗎? { #is-concurrency-better-than-parallelism } @@ -298,7 +298,7 @@ def results(): 這一點,再加上 Python 是 **資料科學**、機器學習,尤其是深度學習的主要語言,讓 **FastAPI** 成為資料科學/機器學習 Web API 和應用程式(以及許多其他應用程式)的絕佳選擇。 -想了解如何在生產環境中實現這種平行性,請參見 [部屬](deployment/index.md){.internal-link target=_blank}。 +想了解如何在生產環境中實現這種平行性,請參見 [部屬](deployment/index.md)。 ## `async` 和 `await` { #async-and-await } @@ -363,13 +363,13 @@ async def read_burgers(): ### 編寫自己的非同步程式碼 { #write-your-own-async-code } -Starlette(和 **FastAPI**)是基於 AnyIO 實作的,這使得它們與 Python 標準函式庫 asyncioTrio 相容。 +Starlette(和 **FastAPI**)是基於 [AnyIO](https://anyio.readthedocs.io/en/stable/) 實作的,這使得它們與 Python 標準函式庫 [asyncio](https://docs.python.org/3/library/asyncio-task.html) 和 [Trio](https://trio.readthedocs.io/en/stable/) 相容。 -特別是,你可以直接使用 AnyIO 來處理更複雜的並行使用案例,這些案例需要你在自己的程式碼中使用更高階的模式。 +特別是,你可以直接使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 來處理更複雜的並行使用案例,這些案例需要你在自己的程式碼中使用更高階的模式。 -即使你不使用 **FastAPI**,你也可以使用 AnyIO 來撰寫自己的非同步應用程式,並獲得高相容性及一些好處(例如「結構化並行」)。 +即使你不使用 **FastAPI**,你也可以使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 來撰寫自己的非同步應用程式,並獲得高相容性及一些好處(例如「結構化並行」)。 -我另外在 AnyIO 之上做了一個薄封裝的函式庫,稍微改進型別註解以獲得更好的**自動補全**、**即時錯誤**等。同時它也提供友善的介紹與教學,幫助你**理解**並撰寫**自己的非同步程式碼**:Asyncer。當你需要**將非同步程式碼與一般**(阻塞/同步)**程式碼整合**時,它特別實用。 +我另外在 AnyIO 之上做了一個薄封裝的函式庫,稍微改進型別註解以獲得更好的**自動補全**、**即時錯誤**等。同時它也提供友善的介紹與教學,幫助你**理解**並撰寫**自己的非同步程式碼**:[Asyncer](https://asyncer.tiangolo.com/)。當你需要**將非同步程式碼與一般**(阻塞/同步)**程式碼整合**時,它特別實用。 ### 其他形式的非同步程式碼 { #other-forms-of-asynchronous-code } @@ -381,7 +381,7 @@ Starlette(和 **FastAPI**)是基於 Gevent。但這些程式碼要更難以理解、調試和思考。 +在較舊的 Python 版本中,你可能會使用多執行緒或 [Gevent](https://www.gevent.org/)。但這些程式碼要更難以理解、調試和思考。 在較舊的 NodeJS / 瀏覽器 JavaScript 中,你會使用「回呼」,這可能會導致“回呼地獄”。 @@ -419,15 +419,15 @@ Starlette(和 **FastAPI**)是基於 I/O 的程式碼。 -不過,在這兩種情況下,**FastAPI** [仍然很快](index.md#performance){.internal-link target=_blank},至少與你之前的框架相當(或者更快)。 +不過,在這兩種情況下,**FastAPI** [仍然很快](index.md#performance),至少與你之前的框架相當(或者更快)。 ### 依賴項(Dependencies) { #dependencies } -同樣適用於[依賴項](tutorial/dependencies/index.md){.internal-link target=_blank}。如果依賴項是一個標準的 `def` 函式,而不是 `async def`,那麼它在外部的執行緒池被運行。 +同樣適用於[依賴項](tutorial/dependencies/index.md)。如果依賴項是一個標準的 `def` 函式,而不是 `async def`,那麼它在外部的執行緒池被運行。 ### 子依賴項 { #sub-dependencies } -你可以擁有多個相互依賴的依賴項和[子依賴項](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank}(作為函式定義的參數),其中一些可能是用 `async def` 宣告,也可能是用 `def` 宣告。它們仍然可以正常運作,用 `def` 定義的那些將會在外部的執行緒中呼叫(來自執行緒池),而不是被「等待」。 +你可以擁有多個相互依賴的依賴項和[子依賴項](tutorial/dependencies/sub-dependencies.md)(作為函式定義的參數),其中一些可能是用 `async def` 宣告,也可能是用 `def` 宣告。它們仍然可以正常運作,用 `def` 定義的那些將會在外部的執行緒中呼叫(來自執行緒池),而不是被「等待」。 ### 其他輔助函式 { #other-utility-functions } diff --git a/docs/zh-hant/docs/benchmarks.md b/docs/zh-hant/docs/benchmarks.md index c5b76700b3..2b5b3f7ee1 100644 --- a/docs/zh-hant/docs/benchmarks.md +++ b/docs/zh-hant/docs/benchmarks.md @@ -1,6 +1,6 @@ # 基準測試 { #benchmarks } -由第三方機構 TechEmpower 的基準測試表明在 Uvicorn 下運行的 **FastAPI** 應用程式是 最快的 Python 可用框架之一,僅次於 Starlette 和 Uvicorn 本身(於 FastAPI 內部使用)。 +由第三方機構 TechEmpower 的基準測試表明在 Uvicorn 下運行的 **FastAPI** 應用程式是 [最快的 Python 可用框架之一](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7),僅次於 Starlette 和 Uvicorn 本身(於 FastAPI 內部使用)。 但是在查看基準得分和對比時,請注意以下幾點。 diff --git a/docs/zh-hant/docs/deployment/cloud.md b/docs/zh-hant/docs/deployment/cloud.md index fffb2fcfeb..86d216ca6f 100644 --- a/docs/zh-hant/docs/deployment/cloud.md +++ b/docs/zh-hant/docs/deployment/cloud.md @@ -6,7 +6,7 @@ ## FastAPI Cloud { #fastapi-cloud } -**FastAPI Cloud** 由 **FastAPI** 的同一位作者與團隊打造。 +**[FastAPI Cloud](https://fastapicloud.com)** 由 **FastAPI** 的同一位作者與團隊打造。 它讓你以最少的投入,簡化 **建置**、**部署** 與 **存取** API 的流程。 @@ -16,9 +16,9 @@ FastAPI Cloud 是 *FastAPI and friends* 開源專案的主要贊助與資金提 ## 雲端供應商 - 贊助商 { #cloud-providers-sponsors } -其他一些雲端供應商也會 ✨ [**贊助 FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨。🙇 +其他一些雲端供應商也會 ✨ [**贊助 FastAPI**](../help-fastapi.md#sponsor-the-author) ✨。🙇 你也可以參考他們的指南並試用其服務: -* Render -* Railway +* [Render](https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi) +* [Railway](https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi) diff --git a/docs/zh-hant/docs/deployment/concepts.md b/docs/zh-hant/docs/deployment/concepts.md index 0cca31d260..0b8677bfd3 100644 --- a/docs/zh-hant/docs/deployment/concepts.md +++ b/docs/zh-hant/docs/deployment/concepts.md @@ -25,7 +25,7 @@ ## 安全性 - HTTPS { #security-https } -在[前一章關於 HTTPS](https.md){.internal-link target=_blank} 中,我們學到 HTTPS 如何為你的 API 提供加密。 +在[前一章關於 HTTPS](https.md) 中,我們學到 HTTPS 如何為你的 API 提供加密。 我們也看到,HTTPS 通常由應用伺服器外部的元件提供,即 TLS Termination Proxy。 @@ -190,7 +190,7 @@ ### 工作行程與連接埠 { #worker-processes-and-ports } -還記得文件中[關於 HTTPS](https.md){.internal-link target=_blank} 的說明嗎:在一台伺服器上,一組 IP 與連接埠的組合只能由「一個行程」監聽? +還記得文件中[關於 HTTPS](https.md) 的說明嗎:在一台伺服器上,一組 IP 與連接埠的組合只能由「一個行程」監聽? 這裡同樣適用。 @@ -243,7 +243,7 @@ 先別擔心這裡提到的「容器」、Docker 或 Kubernetes 如果現在還不太懂。 -我會在未來的章節進一步說明容器映像、Docker、Kubernetes 等等:[容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank}。 +我會在未來的章節進一步說明容器映像、Docker、Kubernetes 等等:[容器中的 FastAPI - Docker](docker.md)。 /// @@ -281,7 +281,7 @@ /// tip -我會在未來關於容器的章節提供更具體的範例:[容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank}。 +我會在未來關於容器的章節提供更具體的範例:[容器中的 FastAPI - Docker](docker.md)。 /// diff --git a/docs/zh-hant/docs/deployment/docker.md b/docs/zh-hant/docs/deployment/docker.md index 87f4e6f9f0..03b9f2f76e 100644 --- a/docs/zh-hant/docs/deployment/docker.md +++ b/docs/zh-hant/docs/deployment/docker.md @@ -1,6 +1,6 @@ # 在容器中使用 FastAPI - Docker { #fastapi-in-containers-docker } -部署 FastAPI 應用時,一個常見做法是建置一個「Linux 容器映像(container image)」。通常使用 Docker 來完成。之後你可以用多種方式部署該容器映像。 +部署 FastAPI 應用時,一個常見做法是建置一個「Linux 容器映像(container image)」。通常使用 [Docker](https://www.docker.com/) 來完成。之後你可以用多種方式部署該容器映像。 使用 Linux 容器有多種優點,包括安全性、可重現性、簡單性等。 @@ -60,16 +60,16 @@ Linux 容器使用與主機(機器、虛擬機、雲端伺服器等)相同 Docker 是用來建立與管理容器映像與容器的主要工具之一。 -也有一個公開的 Docker Hub,內含許多工具、環境、資料庫與應用的預先製作「官方映像」。 +也有一個公開的 [Docker Hub](https://hub.docker.com/),內含許多工具、環境、資料庫與應用的預先製作「官方映像」。 -例如,有官方的 Python 映像。 +例如,有官方的 [Python 映像](https://hub.docker.com/_/python)。 也有許多其他針對不同用途的映像,例如資料庫: -* PostgreSQL -* MySQL -* MongoDB -* Redis 等。 +* [PostgreSQL](https://hub.docker.com/_/postgres) +* [MySQL](https://hub.docker.com/_/mysql) +* [MongoDB](https://hub.docker.com/_/mongo) +* [Redis](https://hub.docker.com/_/redis) 等。 使用預製的容器映像很容易「組合」並使用不同工具。例如,嘗試一個新資料庫。多數情況下,你可以使用官方映像,並僅用環境變數加以設定。 @@ -111,7 +111,7 @@ Docker 是用來建立與管理容器映像與容器的主要工具之一。 最常見的方式是準備一個 `requirements.txt` 檔案,逐行列出套件名稱與版本。 -當然,你會用與在 [關於 FastAPI 版本](versions.md){.internal-link target=_blank} 中讀到的相同概念,來設定版本範圍。 +當然,你會用與在 [關於 FastAPI 版本](versions.md) 中讀到的相同概念,來設定版本範圍。 例如,你的 `requirements.txt` 可能像這樣: @@ -238,7 +238,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] #### 使用 `CMD` 的 Exec 形式 { #use-cmd-exec-form } -Docker 的 `CMD` 指令可以有兩種寫法: +Docker 的 [`CMD`](https://docs.docker.com/reference/dockerfile/#cmd) 指令可以有兩種寫法: ✅ Exec 形式: @@ -254,11 +254,11 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] CMD fastapi run app/main.py --port 80 ``` -務必總是使用 exec 形式,以確保 FastAPI 能夠優雅地關閉,並觸發 [lifespan events](../advanced/events.md){.internal-link target=_blank}。 +務必總是使用 exec 形式,以確保 FastAPI 能夠優雅地關閉,並觸發 [lifespan events](../advanced/events.md)。 -你可以在 Docker 關於 shell 與 exec 形式的文件閱讀更多。 +你可以在 [Docker 關於 shell 與 exec 形式的文件](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form) 閱讀更多。 -使用 `docker compose` 時這會特別明顯。技術細節請見這段 Docker Compose 常見問題:為什麼我的服務要花 10 秒才重新建立或停止? +使用 `docker compose` 時這會特別明顯。技術細節請見這段 Docker Compose 常見問題:[為什麼我的服務要花 10 秒才重新建立或停止?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop) #### 目錄結構 { #directory-structure } @@ -352,7 +352,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage ## 檢查 { #check-it } -你應該可以透過 Docker 容器的網址檢查,例如:http://192.168.99.100/items/5?q=somequeryhttp://127.0.0.1/items/5?q=somequery(或等效的、使用你的 Docker 主機)。 +你應該可以透過 Docker 容器的網址檢查,例如:[http://192.168.99.100/items/5?q=somequery](http://192.168.99.100/items/5?q=somequery) 或 [http://127.0.0.1/items/5?q=somequery](http://127.0.0.1/items/5?q=somequery)(或等效的、使用你的 Docker 主機)。 你會看到類似這樣: @@ -362,17 +362,17 @@ $ docker run -d --name mycontainer -p 80:80 myimage ## 互動式 API 文件 { #interactive-api-docs } -現在你可以前往 http://192.168.99.100/docshttp://127.0.0.1/docs(或等效的、使用你的 Docker 主機)。 +現在你可以前往 [http://192.168.99.100/docs](http://192.168.99.100/docs) 或 [http://127.0.0.1/docs](http://127.0.0.1/docs)(或等效的、使用你的 Docker 主機)。 -你會看到自動產生的互動式 API 文件(由 Swagger UI 提供): +你會看到自動產生的互動式 API 文件(由 [Swagger UI](https://github.com/swagger-api/swagger-ui) 提供): ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) ## 替代的 API 文件 { #alternative-api-docs } -你也可以前往 http://192.168.99.100/redochttp://127.0.0.1/redoc(或等效的、使用你的 Docker 主機)。 +你也可以前往 [http://192.168.99.100/redoc](http://192.168.99.100/redoc) 或 [http://127.0.0.1/redoc](http://127.0.0.1/redoc)(或等效的、使用你的 Docker 主機)。 -你會看到另一種自動產生的文件(由 ReDoc 提供): +你會看到另一種自動產生的文件(由 [ReDoc](https://github.com/Rebilly/ReDoc) 提供): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -413,7 +413,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] ## 部署概念 { #deployment-concepts } -我們用容器的角度再談一次部分相同的[部署概念](concepts.md){.internal-link target=_blank}。 +我們用容器的角度再談一次部分相同的[部署概念](concepts.md)。 容器主要是簡化應用「建置與部署」流程的工具,但它們不強制特定的方式來處理這些「部署概念」,而是有多種策略可選。 @@ -432,7 +432,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] 若僅聚焦於 FastAPI 應用的「容器映像」(以及稍後的執行中「容器」),HTTPS 通常會由另一個工具在「外部」處理。 -它可以是另一個容器,例如使用 Traefik,來處理「HTTPS」以及「自動」取得「憑證」。 +它可以是另一個容器,例如使用 [Traefik](https://traefik.io/),來處理「HTTPS」以及「自動」取得「憑證」。 /// tip | 提示 @@ -454,7 +454,7 @@ Traefik 與 Docker、Kubernetes 等整合良好,因此為你的容器設定與 ## 複本 - 行程數量 { #replication-number-of-processes } -如果你在有 Kubernetes、Docker Swarm Mode、Nomad,或其他類似的分散式容器管理系統的「叢集」上運作,那你大概會希望在「叢集層級」處理「複本」,而不是在每個容器內使用「行程管理器」(例如帶有 workers 的 Uvicorn)。 +如果你在有 Kubernetes、Docker Swarm Mode、Nomad,或其他類似的分散式容器管理系統的「叢集」上運作,那你大概會希望在「叢集層級」處理「複本」,而不是在每個容器內使用「行程管理器」(例如帶有 workers 的 Uvicorn)。 像 Kubernetes 這類的分散式容器管理系統,通常內建處理「容器複本」以及支援進入請求的「負載平衡」的能力——全部都在「叢集層級」。 @@ -558,7 +558,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] /// info | 資訊 -如果你使用 Kubernetes,這大概會是一個 Init Container。 +如果你使用 Kubernetes,這大概會是一個 [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)。 /// @@ -570,7 +570,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] ### 基底 Docker 映像 { #base-docker-image } -曾經有一個官方的 FastAPI Docker 映像:tiangolo/uvicorn-gunicorn-fastapi。但現在已被棄用。⛔️ +曾經有一個官方的 FastAPI Docker 映像:[tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker)。但現在已被棄用。⛔️ 你大概「不應該」使用這個基底 Docker 映像(或其他類似的)。 @@ -600,7 +600,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] ## 使用 `uv` 的 Docker 映像 { #docker-image-with-uv } -如果你使用 uv 來安裝與管理專案,你可以參考他們的 uv Docker 指南。 +如果你使用 [uv](https://github.com/astral-sh/uv) 來安裝與管理專案,你可以參考他們的 [uv Docker 指南](https://docs.astral.sh/uv/guides/integration/docker/)。 ## 總結 { #recap } diff --git a/docs/zh-hant/docs/deployment/fastapicloud.md b/docs/zh-hant/docs/deployment/fastapicloud.md index 5663590d14..4b6fb86b47 100644 --- a/docs/zh-hant/docs/deployment/fastapicloud.md +++ b/docs/zh-hant/docs/deployment/fastapicloud.md @@ -1,6 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -你可以用「一行指令」把你的 FastAPI 應用程式部署到 FastAPI Cloud。如果你還沒加入,快去登記等候名單吧!🚀 +你可以用「一行指令」把你的 FastAPI 應用程式部署到 [FastAPI Cloud](https://fastapicloud.com)。如果你還沒加入,快去登記等候名單吧!🚀 ## 登入 { #login } @@ -40,7 +40,7 @@ Deploying to FastAPI Cloud... ## 關於 FastAPI Cloud { #about-fastapi-cloud } -**FastAPI Cloud** 由 **FastAPI** 的作者與團隊打造。 +**[FastAPI Cloud](https://fastapicloud.com)** 由 **FastAPI** 的作者與團隊打造。 它以最少的心力,精簡化建立、部署與存取 API 的流程。 diff --git a/docs/zh-hant/docs/deployment/https.md b/docs/zh-hant/docs/deployment/https.md index 0934b02831..ddafcb34b1 100644 --- a/docs/zh-hant/docs/deployment/https.md +++ b/docs/zh-hant/docs/deployment/https.md @@ -10,7 +10,7 @@ /// -想從使用者角度學習 HTTPS 基礎,請參考 https://howhttps.works/。 +想從使用者角度學習 HTTPS 基礎,請參考 [https://howhttps.works/](https://howhttps.works/)。 接著以開發者角度,談幾個關於 HTTPS 需要注意的重點: @@ -28,13 +28,13 @@ * **預設**情況下,這表示你每個 IP 位址**只能**使用**一張 HTTPS 憑證**。 * 不論你的伺服器多強或你在上面跑的應用多小。 * 不過,這是有**解法**的。 -* 在 **TLS** 協定(在 HTTP 之前於 TCP 層處理加密的協定)上有個**擴充**稱為 **SNI**。 +* 在 **TLS** 協定(在 HTTP 之前於 TCP 層處理加密的協定)上有個**擴充**稱為 **[SNI](https://en.wikipedia.org/wiki/Server_Name_Indication)**。 * 這個 SNI 擴充讓單一伺服器(單一 IP 位址)可以擁有**多張 HTTPS 憑證**,並服務**多個 HTTPS 網域/應用**。 * 要讓它運作,伺服器上必須有一個**單一**的元件(程式)在**公用 IP**上監聽,且持有伺服器上的**所有 HTTPS 憑證**。 * 在取得安全連線**之後**,通訊協定**仍然是 HTTP**。 * 雖然透過 **HTTP 協定**傳送,但內容是**加密**的。 -常見做法是讓伺服器(機器、主機等)上跑**一個程式/HTTP 伺服器**來**管理所有 HTTPS 相關工作**:接收**加密的 HTTPS 請求**、將其**解密**成**純 HTTP 請求**轉交給同台伺服器上實際運行的 HTTP 應用(本例為 **FastAPI** 應用)、從應用取得 **HTTP 回應**、再用合適的 **HTTPS 憑證**將其**加密**並以 **HTTPS** 傳回給用戶端。這類伺服器常被稱為 **TLS 終止代理 (TLS Termination Proxy)**。 +常見做法是讓伺服器(機器、主機等)上跑**一個程式/HTTP 伺服器**來**管理所有 HTTPS 相關工作**:接收**加密的 HTTPS 請求**、將其**解密**成**純 HTTP 請求**轉交給同台伺服器上實際運行的 HTTP 應用(本例為 **FastAPI** 應用)、從應用取得 **HTTP 回應**、再用合適的 **HTTPS 憑證**將其**加密**並以 **HTTPS** 傳回給用戶端。這類伺服器常被稱為 **[TLS 終止代理](https://en.wikipedia.org/wiki/TLS_termination_proxy)**。 可作為 TLS 終止代理的選項包括: @@ -49,7 +49,7 @@ 取得這些憑證的流程過去相當繁瑣,需要許多手續,且憑證相當昂貴。 -之後出現了 **Let's Encrypt**。 +之後出現了 **[Let's Encrypt](https://letsencrypt.org/)**。 它是 Linux Foundation 的專案,能**免費**且自動化地提供 **HTTPS 憑證**。這些憑證採用標準的密碼學安全機制,且有效期較短(約 3 個月),因此因為壽命短,**安全性其實更好**。 @@ -200,9 +200,9 @@ TLS 終止代理接著會依照先前協商(起點是 `someapp.example.com` 這些代理標頭包括: -* X-Forwarded-For -* X-Forwarded-Proto -* X-Forwarded-Host +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) /// @@ -218,7 +218,7 @@ TLS 終止代理接著會依照先前協商(起點是 `someapp.example.com` /// tip -你可以在文件 [在代理後方 - 啟用代理轉發標頭](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} 中了解更多。 +你可以在文件 [在代理後方 - 啟用代理轉發標頭](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) 中了解更多。 /// diff --git a/docs/zh-hant/docs/deployment/index.md b/docs/zh-hant/docs/deployment/index.md index ddf533efc9..c9d474cacb 100644 --- a/docs/zh-hant/docs/deployment/index.md +++ b/docs/zh-hant/docs/deployment/index.md @@ -16,7 +16,7 @@ 你可以使用一些工具自行**部署伺服器**,你也可以使用能為你完成部分工作的**雲端服務**,或其他可能的選項。 -例如,我們(FastAPI 的團隊)打造了 **FastAPI Cloud**,讓將 FastAPI 應用程式部署到雲端變得盡可能流暢,並保持與使用 FastAPI 開發時相同的開發者體驗。 +例如,我們(FastAPI 的團隊)打造了 [**FastAPI Cloud**](https://fastapicloud.com),讓 FastAPI 應用程式部署到雲端變得盡可能流暢,並保持與使用 FastAPI 開發時相同的開發者體驗。 我將向你展示在部署 **FastAPI** 應用程式時你可能應該記住的一些主要概念(儘管其中大部分適用於任何其他類型的 Web 應用程式)。 diff --git a/docs/zh-hant/docs/deployment/manually.md b/docs/zh-hant/docs/deployment/manually.md index bf9f6a93f4..71e9e27c87 100644 --- a/docs/zh-hant/docs/deployment/manually.md +++ b/docs/zh-hant/docs/deployment/manually.md @@ -52,11 +52,11 @@ FastAPI 採用建立 Python 網頁框架與伺服器的標準 Uvicorn:高效能 ASGI 伺服器。 -* Hypercorn:支援 HTTP/2 與 Trio 等功能的 ASGI 伺服器。 -* Daphne:為 Django Channels 打造的 ASGI 伺服器。 -* Granian:針對 Python 應用的 Rust HTTP 伺服器。 -* NGINX Unit:NGINX Unit 是輕量且多功能的網頁應用執行環境。 +* [Uvicorn](https://www.uvicorn.dev/):高效能 ASGI 伺服器。 +* [Hypercorn](https://hypercorn.readthedocs.io/):支援 HTTP/2 與 Trio 等功能的 ASGI 伺服器。 +* [Daphne](https://github.com/django/daphne):為 Django Channels 打造的 ASGI 伺服器。 +* [Granian](https://github.com/emmett-framework/granian):針對 Python 應用的 Rust HTTP 伺服器。 +* [NGINX Unit](https://unit.nginx.org/howto/fastapi/):NGINX Unit 是輕量且多功能的網頁應用執行環境。 ## 伺服器機器與伺服器程式 { #server-machine-and-server-program } @@ -74,7 +74,7 @@ FastAPI 採用建立 Python 網頁框架與伺服器的標準 語意化版本(Semantic Versioning) 的慣例。 +這就是為什麼目前版本仍為 `0.x.x`,這表示每個版本都可能包含破壞性變更。這遵循 [語意化版本(Semantic Versioning)](https://semver.org/) 的慣例。 你現在就可以用 **FastAPI** 建置生產環境的應用(而且你可能已經這麼做一段時間了),只要確保你使用的版本能與其餘程式碼正確相容。 @@ -34,7 +34,7 @@ fastapi[standard]>=0.112.0,<0.113.0 ## 可用版本 { #available-versions } -你可以在 [發行說明](../release-notes.md){.internal-link target=_blank} 查看可用版本(例如用來確認目前最新版本)。 +你可以在 [發行說明](../release-notes.md) 查看可用版本(例如用來確認目前最新版本)。 ## 關於版本 { #about-versions } @@ -66,7 +66,7 @@ fastapi>=0.45.0,<0.46.0 你應該為你的應用撰寫測試。 -在 **FastAPI** 中這很容易(感謝 Starlette),請參考文件:[測試](../tutorial/testing.md){.internal-link target=_blank} +在 **FastAPI** 中這很容易(感謝 Starlette),請參考文件:[測試](../tutorial/testing.md) 有了測試之後,你就可以將 **FastAPI** 升級到較新的版本,並透過執行測試來確保所有程式碼都能正確運作。 diff --git a/docs/zh-hant/docs/environment-variables.md b/docs/zh-hant/docs/environment-variables.md index 5b684b9e6a..09264b7e26 100644 --- a/docs/zh-hant/docs/environment-variables.md +++ b/docs/zh-hant/docs/environment-variables.md @@ -65,7 +65,7 @@ print(f"Hello {name} from Python") /// tip -第二個參數是 `os.getenv()` 的預設回傳值。 +第二個參數是 [`os.getenv()`](https://docs.python.org/3.8/library/os.html#os.getenv) 的預設回傳值。 如果沒有提供,預設值為 `None`,這裡我們提供 `"World"` 作為預設值。 @@ -153,7 +153,7 @@ Hello World from Python /// tip -你可以在 The Twelve-Factor App: 配置中了解更多資訊。 +你可以在 [The Twelve-Factor App: 配置](https://12factor.net/config) 中了解更多資訊。 /// @@ -163,7 +163,7 @@ Hello World from Python 這意味著從環境變數中讀取的**任何值**在 Python 中都將是一個 `str`,任何型別轉換或驗證都必須在程式碼中完成。 -你將在[進階使用者指南 - 設定和環境變數](./advanced/settings.md){.internal-link target=_blank}中了解更多關於使用環境變數處理**應用程式設定**的資訊。 +你將在[進階使用者指南 - 設定和環境變數](./advanced/settings.md)中了解更多關於使用環境變數處理**應用程式設定**的資訊。 ## `PATH` 環境變數 { #path-environment-variable } @@ -285,13 +285,13 @@ $ C:\opt\custompython\bin\python //// -當學習[虛擬環境](virtual-environments.md){.internal-link target=_blank}時,這些資訊將會很有用。 +當學習[虛擬環境](virtual-environments.md)時,這些資訊將會很有用。 ## 結論 { #conclusion } 透過這個教學,你應該對**環境變數**是什麼以及如何在 Python 中使用它們有了基本的了解。 -你也可以在 環境變數的維基百科條目 中閱讀更多。 +你也可以在 [環境變數的維基百科條目](https://en.wikipedia.org/wiki/Environment_variable) 中閱讀更多。 在許多情況下,環境變數的用途和適用性可能不會立刻顯現。但是在開發過程中,它們會在許多不同的場景中出現,因此瞭解它們是非常必要的。 diff --git a/docs/zh-hant/docs/fastapi-cli.md b/docs/zh-hant/docs/fastapi-cli.md index 57b5ec98f2..554ef4f2df 100644 --- a/docs/zh-hant/docs/fastapi-cli.md +++ b/docs/zh-hant/docs/fastapi-cli.md @@ -1,15 +1,15 @@ # FastAPI CLI { #fastapi-cli } -**FastAPI CLI** 是一個命令列程式,能用來運行你的 FastAPI 應用程式、管理你的 FastAPI 專案等。 +**FastAPI CLI** 是一個命令列程式,你可以用它來啟動你的 FastAPI 應用程式、管理你的 FastAPI 專案,等等。 -當你安裝 FastAPI(例如使用 `pip install "fastapi[standard]"`),它會包含一個叫做 `fastapi-cli` 的套件,這個套件提供了 `fastapi` 命令。 +當你安裝 FastAPI(例如使用 `pip install "fastapi[standard]"`)時,會附帶一個可以在終端機執行的命令列程式。 -要運行你的 FastAPI 應用程式來進行開發,你可以使用 `fastapi dev` 命令: +要在開發時運行你的 FastAPI 應用程式,你可以使用 `fastapi dev` 指令:
```console -$ fastapi dev main.py +$ fastapi dev FastAPI Starting development server 🚀 @@ -46,13 +46,66 @@ $ fastapi dev Uvicorn,這是一個高效能、適合生產環境的 ASGI 伺服器。 😎 +此外,其他工具可能找不到它,例如 [VS Code 擴充套件](editor-support.md) 或 [FastAPI Cloud](https://fastapicloud.com),因此建議在 `pyproject.toml` 中使用 `entrypoint`。 ## `fastapi dev` { #fastapi-dev } @@ -70,6 +123,6 @@ FastAPI CLI 接收你的 Python 程式路徑(例如 `main.py`),並自動 /// tip -你可以在[部署文件](deployment/index.md){.internal-link target=_blank}中了解更多相關資訊。 +你可以在[部署文件](deployment/index.md)中了解更多相關資訊。 /// diff --git a/docs/zh-hant/docs/features.md b/docs/zh-hant/docs/features.md index 77c0203073..63194e2556 100644 --- a/docs/zh-hant/docs/features.md +++ b/docs/zh-hant/docs/features.md @@ -6,8 +6,8 @@ ### 建立在開放標準的基礎上 { #based-on-open-standards } -* 使用 OpenAPI 來建立 API,包含 路徑操作、參數、請求內文、安全性等宣告。 -* 使用 JSON Schema(因為 OpenAPI 本身就是基於 JSON Schema)自動生成資料模型文件。 +* 使用 [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) 來建立 API,包含 路徑操作、參數、請求內文、安全性等宣告。 +* 使用 [**JSON Schema**](https://json-schema.org/)(因為 OpenAPI 本身就是基於 JSON Schema)自動生成資料模型文件。 * 經過縝密的研究後圍繞這些標準進行設計,而不是事後在已有系統上附加的一層功能。 * 這也讓我們在多種語言中可以使用自動**用戶端程式碼生成**。 @@ -15,11 +15,11 @@ FastAPI 能生成互動式 API 文件和探索性的 Web 使用者介面。由於該框架基於 OpenAPI,因此有多種選擇,預設提供了兩種。 -* Swagger UI 提供互動式探索,讓你可以直接從瀏覽器呼叫並測試你的 API 。 +* [**Swagger UI**](https://github.com/swagger-api/swagger-ui) 提供互動式探索,讓你可以直接從瀏覽器呼叫並測試你的 API 。 ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* 使用 ReDoc 的替代 API 文件。 +* 使用 [**ReDoc**](https://github.com/Rebilly/ReDoc) 的替代 API 文件。 ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) @@ -27,7 +27,7 @@ FastAPI 能生成互動式 API 文件和探索性的 Web 使用者介面。由 這一切都基於標準的 **Python 型別**宣告(感謝 Pydantic)。無需學習新的語法,只需使用標準的現代 Python。 -如果你需要 2 分鐘來學習如何使用 Python 型別(即使你不使用 FastAPI),可以看看這個簡短的教學:[Python 型別](python-types.md){.internal-link target=_blank}。 +如果你需要 2 分鐘來學習如何使用 Python 型別(即使你不使用 FastAPI),可以看看這個簡短的教學:[Python 型別](python-types.md)。 如果你寫帶有 Python 型別的程式碼: @@ -75,7 +75,7 @@ my_second_user: User = User(**second_user_data) 整個框架的設計是為了讓使用變得簡單且直觀,在開始開發之前,所有決策都在多個編輯器上進行了測試,以確保提供最佳的開發體驗。 -在最近的 Python 開發者調查中,我們能看到 被使用最多的功能是 autocompletion。 +在最近的 Python 開發者調查中,我們能看到[被使用最多的功能是 autocompletion](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features)。 整個 **FastAPI** 框架就是基於這一點,任何地方都可以進行自動補齊。 @@ -83,11 +83,11 @@ my_second_user: User = User(**second_user_data) 在這裡,你的編輯器可能會這樣幫助你: -* 在 Visual Studio Code 中: +* 在 [Visual Studio Code](https://code.visualstudio.com/) 中: ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -* 在 PyCharm 中: +* 在 [PyCharm](https://www.jetbrains.com/pycharm/) 中: ![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) @@ -124,13 +124,13 @@ FastAPI 已經整合了安全性和身份驗證的功能,但不會強制與特 OpenAPI 中定義的安全模式,包括: * HTTP 基本認證。 -* **OAuth2**(也使用 **JWT tokens**)。在 [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank} 查看教學。 +* **OAuth2**(也使用 **JWT tokens**)。在 [OAuth2 with JWT](tutorial/security/oauth2-jwt.md) 查看教學。 * API 密鑰,在: * 標頭(Header) * 查詢參數 * Cookies,等等。 -加上来自 Starlette(包括 **session cookie**)的所有安全特性。 +加上來自 Starlette(包括 **session cookie**)的所有安全特性。 所有的這些都是可重複使用的工具和套件,可以輕鬆與你的系統、資料儲存(Data Stores)、關聯式資料庫(RDBMS)以及非關聯式資料庫(NoSQL)等等整合。 @@ -159,11 +159,11 @@ FastAPI 有一個使用簡單,但是非常強大的 Pydantic。所以,你有其他 Pydantic 程式碼也能正常工作。 +**FastAPI** 完全相容且基於 [**Pydantic**](https://docs.pydantic.dev/)。所以,你有其他 Pydantic 程式碼也能正常工作。 相容包括基於 Pydantic 的外部函式庫,例如用於資料庫的 ORMs、ODMs。 diff --git a/docs/zh-hant/docs/help-fastapi.md b/docs/zh-hant/docs/help-fastapi.md index 911c566792..343e0dba3e 100644 --- a/docs/zh-hant/docs/help-fastapi.md +++ b/docs/zh-hant/docs/help-fastapi.md @@ -12,7 +12,7 @@ ## 訂閱電子報 { #subscribe-to-the-newsletter } -你可以訂閱(不常發送的)[**FastAPI 與夥伴**電子報](newsletter.md){.internal-link target=_blank},隨時掌握: +你可以訂閱(不常發送的)[**FastAPI 與夥伴**電子報](newsletter.md),隨時掌握: * 關於 FastAPI 與夥伴的最新消息 🚀 * 教學指南 📝 @@ -22,17 +22,17 @@ ## 在 X(Twitter)關注 FastAPI { #follow-fastapi-on-x-twitter } -在 **X(Twitter)** 關注 @fastapi,獲取 **FastAPI** 的最新消息。🐦 +[在 **X(Twitter)** 關注 @fastapi](https://x.com/fastapi),獲取 **FastAPI** 的最新消息。🐦 ## 在 GitHub 為 **FastAPI** 加星 { #star-fastapi-in-github } -你可以在 GitHub 為 FastAPI「加星」(點擊右上角的 star 星號按鈕):https://github.com/fastapi/fastapi。⭐️ +你可以在 GitHub 為 FastAPI「加星」(點擊右上角的 star 星號按鈕):[https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi)。⭐️ 加上星標後,其他使用者會更容易發現它,並看到它已經對許多人很有幫助。 ## 追蹤 GitHub 儲存庫的發行版 { #watch-the-github-repository-for-releases } -你可以在 GitHub「watch」FastAPI(點擊右上角的「watch」按鈕):https://github.com/fastapi/fastapi。👀 +你可以在 GitHub「watch」FastAPI(點擊右上角的「watch」按鈕):[https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi)。👀 在那裡你可以選擇「Releases only」。 @@ -40,45 +40,45 @@ ## 與作者連結 { #connect-with-the-author } -你可以與作者 我(Sebastián Ramírez / `tiangolo`) 建立連結。 +你可以與作者 [我(Sebastián Ramírez / `tiangolo`)](https://tiangolo.com) 建立連結。 你可以: -* 在 **GitHub** 關注我。 +* [在 **GitHub** 關注我](https://github.com/tiangolo)。 * 看看我建立的其他開源專案,可能對你有幫助。 * 關注我以便知道我何時建立新的開源專案。 -* 在 **X(Twitter)**Mastodon 關注我。 +* [在 **X(Twitter)**](https://x.com/tiangolo) 或 [Mastodon](https://fosstodon.org/@tiangolo) 關注我。 * 告訴我你如何使用 FastAPI(我很愛聽這些)。 * 接收我發布公告或釋出新工具時的消息。 - * 你也可以在 X(Twitter)關注 @fastapi(另外的帳號)。 -* 在 **LinkedIn** 關注我。 + * 你也可以[在 X(Twitter)關注 @fastapi](https://x.com/fastapi)(另外的帳號)。 +* [在 **LinkedIn** 關注我](https://www.linkedin.com/in/tiangolo/)。 * 接收我發布公告或釋出新工具時的消息(不過我更常用 X(Twitter)🤷‍♂)。 -* 在 **Dev.to****Medium** 閱讀我寫的內容(或關注我)。 +* 在 [**Dev.to**](https://dev.to/tiangolo) 或 [**Medium**](https://medium.com/@tiangolo) 閱讀我寫的內容(或關注我)。 * 閱讀我的想法、文章,以及我建立的工具。 * 關注我以便在我發佈新內容時能第一時間看到。 ## 在 X(Twitter)發文談談 **FastAPI** { #tweet-about-fastapi } -發一則關於 **FastAPI** 的推文,讓我與其他人知道你為什麼喜歡它。🎉 +[發一則關於 **FastAPI** 的推文](https://x.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi),讓我與其他人知道你為什麼喜歡它。🎉 我很樂於聽到 **FastAPI** 是如何被使用、你喜歡它的哪些地方、在哪個專案/公司使用它等等。 ## 為 FastAPI 投票 { #vote-for-fastapi } -* 在 Slant 為 **FastAPI** 投票。 -* 在 AlternativeTo 為 **FastAPI** 投票。 -* 在 StackShare 表示你使用 **FastAPI**。 +* [在 Slant 為 **FastAPI** 投票](https://www.slant.co/options/34241/~fastapi-review)。 +* [在 AlternativeTo 為 **FastAPI** 投票](https://alternativeto.net/software/fastapi/about/)。 +* [在 StackShare 表示你使用 **FastAPI**](https://stackshare.io/pypi-fastapi)。 ## 在 GitHub 幫助他人解答問題 { #help-others-with-questions-in-github } 你可以嘗試幫助他人回答以下地方的問題: -* GitHub Discussions -* GitHub Issues +* [GitHub Discussions](https://github.com/fastapi/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered) +* [GitHub Issues](https://github.com/fastapi/fastapi/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Aquestion+-label%3Aanswered+) 很多時候你可能已經知道這些問題的解答。🤓 -如果你經常幫大家解決問題,你會成為官方的 [FastAPI 專家](fastapi-people.md#fastapi-experts){.internal-link target=_blank}。🎉 +如果你經常幫大家解決問題,你會成為官方的 [FastAPI 專家](fastapi-people.md#fastapi-experts)。🎉 請記得,最重要的是:盡量友善。大家可能帶著挫折而來,很多時候提問方式不夠理想,但請盡你所能保持友善。🤗 @@ -104,7 +104,7 @@ 很多時候他們只會貼出一小段程式碼,但那不足以**重現問題**。 -* 你可以請他們提供一個最小可重現範例,讓你可以**複製貼上**並在本機執行,看到與他們相同的錯誤或行為,或更好地理解他們的使用情境。 +* 你可以請他們提供一個[最小可重現範例](https://stackoverflow.com/help/minimal-reproducible-example),讓你可以**複製貼上**並在本機執行,看到與他們相同的錯誤或行為,或更好地理解他們的使用情境。 * 如果你有心力,你也可以嘗試自己**建立一個範例**,僅依據問題描述來還原。不過請記得這可能很耗時,或許更好的是先請他們把問題說清楚。 @@ -124,7 +124,7 @@ ## 追蹤 GitHub 儲存庫 { #watch-the-github-repository } -你可以在 GitHub「watch」FastAPI(點擊右上角的「watch」按鈕):https://github.com/fastapi/fastapi。👀 +你可以在 GitHub「watch」FastAPI(點擊右上角的「watch」按鈕):[https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi)。👀 如果你選擇「Watching」而不是「Releases only」,當有人建立新的 issue 或問題時你會收到通知。你也可以指定只想被通知新的 issues、discussions、PR 等等。 @@ -132,7 +132,7 @@ ## 提問 { #ask-questions } -你可以在 GitHub 儲存庫建立一個新的問題(Question),例如用來: +你可以在 GitHub 儲存庫[建立一個新的問題(Question)](https://github.com/fastapi/fastapi/discussions/new?category=questions),例如用來: * 提出**問題**或詢問某個**疑難**。 * 建議一個新的**功能**。 @@ -195,12 +195,12 @@ ## 建立 Pull Request { #create-a-pull-request } -你可以透過 Pull Request 來[貢獻](contributing.md){.internal-link target=_blank}原始碼,例如: +你可以透過 Pull Request 來[貢獻](contributing.md)原始碼,例如: * 修正文檔中你發現的錯字。 -* 分享你建立或發現的 FastAPI 相關文章、影片或 podcast,方法是編輯這個檔案。 +* 分享你建立或發現的 FastAPI 相關文章、影片或 podcast,方法是[編輯這個檔案](https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml)。 * 請確保把你的連結加到對應章節的開頭。 -* 協助把[文件翻譯](contributing.md#translations){.internal-link target=_blank}成你的語言。 +* 協助把[文件翻譯](contributing.md#translations)成你的語言。 * 你也可以幫忙審查他人提交的翻譯。 * 提議新的文件章節。 * 修復既有的 issue/bug。 @@ -217,8 +217,8 @@ 你現在就能做的主要任務有: -* [在 GitHub 幫助他人解答問題](#help-others-with-questions-in-github){.internal-link target=_blank}(見上方章節)。 -* [審核 Pull Request](#review-pull-requests){.internal-link target=_blank}(見上方章節)。 +* [在 GitHub 幫助他人解答問題](#help-others-with-questions-in-github)(見上方章節)。 +* [審核 Pull Request](#review-pull-requests)(見上方章節)。 這兩件事是**最耗時**的。這也是維護 FastAPI 的主要工作。 @@ -226,11 +226,11 @@ ## 加入聊天室 { #join-the-chat } -加入 👥 Discord 聊天伺服器 👥,與 FastAPI 社群的其他人一起交流。 +加入 👥 [Discord 聊天伺服器](https://discord.gg/VQjSZaeJmf) 👥,與 FastAPI 社群的其他人一起交流。 /// tip -若要提問,請到 GitHub Discussions,在那裡更有機會獲得[FastAPI 專家](fastapi-people.md#fastapi-experts){.internal-link target=_blank}的協助。 +若要提問,請到 [GitHub Discussions](https://github.com/fastapi/fastapi/discussions/new?category=questions),在那裡更有機會獲得[FastAPI 專家](fastapi-people.md#fastapi-experts)的協助。 聊天室請僅用於其他一般性的交流。 @@ -242,13 +242,13 @@ 在 GitHub 上,模板會引導你寫出合適的提問,讓你更容易得到好的解答,甚至在提問前就自己解決問題。而且在 GitHub 上,我能確保最終都會回覆(即使需要一些時間)。我個人無法在聊天系統做到這一點。😅 -聊天系統中的對話也不像 GitHub 那樣容易被搜尋,因此問題與答案可能在對話中淹沒。而且只有 GitHub 上的問題與回答才會被計入成為[FastAPI 專家](fastapi-people.md#fastapi-experts){.internal-link target=_blank},因此你在 GitHub 上更有機會獲得關注。 +聊天系統中的對話也不像 GitHub 那樣容易被搜尋,因此問題與答案可能在對話中淹沒。而且只有 GitHub 上的問題與回答才會被計入成為[FastAPI 專家](fastapi-people.md#fastapi-experts),因此你在 GitHub 上更有機會獲得關注。 另一方面,聊天室裡有成千上萬的使用者,所以幾乎隨時都有很大的機會能找到人聊天。😄 ## 贊助作者 { #sponsor-the-author } -如果你的**產品/公司**依賴或與 **FastAPI** 相關,且你想觸及它的使用者,你可以透過 GitHub sponsors 贊助作者(我)。依據不同級別,你可能會得到一些額外福利,例如在文件中顯示徽章。🎁 +如果你的**產品/公司**依賴或與 **FastAPI** 相關,且你想觸及它的使用者,你可以透過 [GitHub sponsors](https://github.com/sponsors/tiangolo) 贊助作者(我)。依據不同級別,你可能會得到一些額外福利,例如在文件中顯示徽章。🎁 --- diff --git a/docs/zh-hant/docs/history-design-future.md b/docs/zh-hant/docs/history-design-future.md index b7f57a3636..f3c733330a 100644 --- a/docs/zh-hant/docs/history-design-future.md +++ b/docs/zh-hant/docs/history-design-future.md @@ -1,6 +1,6 @@ # 歷史、設計與未來 { #history-design-and-future } -不久之前,一位 **FastAPI** 使用者提問: +不久之前,[一位 **FastAPI** 使用者提問](https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920): > 這個專案的歷史是什麼?看起來它在短短幾週內從默默無名變得非常厲害 [...] @@ -14,7 +14,7 @@ **FastAPI** 的歷史,在很大程度上也是其前身工具的歷史。 -如在[替代方案](alternatives.md){.internal-link target=_blank}章節所述: +如在[替代方案](alternatives.md)一節所述:
@@ -44,9 +44,9 @@ 我在最受歡迎的 Python 編輯器中測試了多個想法:PyCharm、VS Code、基於 Jedi 的編輯器。 -根據最新的 Python 開發者調查,這些工具涵蓋約 80% 的使用者。 +根據最新的 [Python 開發者調查](https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools),這些工具涵蓋約 80% 的使用者。 -這表示 **FastAPI** 已針對 80% 的 Python 開發者所使用的編輯器進行過專門測試。而由於其他多數編輯器的行為也類似,這些優點幾乎在所有編輯器上都能生效。 +這表示 **FastAPI** 已針對 80% 的 Python 開發者所使用的編輯器進行過專門測試。而由於其他多數編輯器的行為也類似,這些優點擴及實際上幾乎所有編輯器。 藉此我找到了盡可能減少程式碼重複、在各處提供自動補全、型別與錯誤檢查等的最佳方式。 @@ -54,11 +54,11 @@ ## 需求 { #requirements } -在測試多種替代方案後,我決定採用 **Pydantic**,因為它的優勢。 +在測試多種替代方案後,我決定採用 [**Pydantic**](https://docs.pydantic.dev/),因為它的優勢。 隨後我也對它做出貢獻,使其完全符合 JSON Schema、支援以不同方式定義約束,並依據在多款編輯器中的測試結果改進編輯器支援(型別檢查、自動補全)。 -在開發過程中,我也對 **Starlette**(另一個關鍵依賴)做出貢獻。 +在開發過程中,我也對 [**Starlette**](https://www.starlette.dev/)(另一個關鍵依賴)做出貢獻。 ## 開發 { #development } @@ -76,4 +76,4 @@ **FastAPI** 的前景非常光明。 -也非常感謝[你的幫助](help-fastapi.md){.internal-link target=_blank}。 +也非常感謝[你的幫助](help-fastapi.md)。 diff --git a/docs/zh-hant/docs/how-to/authentication-error-status-code.md b/docs/zh-hant/docs/how-to/authentication-error-status-code.md index 9a8de4c910..beea430707 100644 --- a/docs/zh-hant/docs/how-to/authentication-error-status-code.md +++ b/docs/zh-hant/docs/how-to/authentication-error-status-code.md @@ -2,7 +2,7 @@ 在 FastAPI 版本 `0.122.0` 之前,當內建的安全工具在身分驗證失敗後回傳錯誤給用戶端時,會使用 HTTP 狀態碼 `403 Forbidden`。 -從 FastAPI 版本 `0.122.0` 起,改為使用更合適的 HTTP 狀態碼 `401 Unauthorized`,並在回應中依據 HTTP 規範加上合理的 `WWW-Authenticate` 標頭,參考 RFC 7235RFC 9110。 +從 FastAPI 版本 `0.122.0` 起,改為使用更合適的 HTTP 狀態碼 `401 Unauthorized`,並在回應中依據 HTTP 規範加上合理的 `WWW-Authenticate` 標頭,參考 [RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-3.1)、[RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized)。 但如果你的用戶端因某些原因依賴於舊行為,你可以在你的 security 類別中覆寫 `make_not_authenticated_error` 方法以恢復舊的行為。 diff --git a/docs/zh-hant/docs/how-to/conditional-openapi.md b/docs/zh-hant/docs/how-to/conditional-openapi.md index 5c091e5b7b..485a7d11d7 100644 --- a/docs/zh-hant/docs/how-to/conditional-openapi.md +++ b/docs/zh-hant/docs/how-to/conditional-openapi.md @@ -10,7 +10,7 @@ 若你的程式碼有安全性缺陷,它依然會存在。 -隱藏文件只會讓他人更難理解如何與你的 API 互動,也可能讓你在正式環境除錯更困難。這通常僅被視為一種 以隱匿求安全。 +隱藏文件只會讓他人更難理解如何與你的 API 互動,也可能讓你在正式環境除錯更困難。這通常僅被視為一種 [以隱匿求安全](https://en.wikipedia.org/wiki/Security_through_obscurity)。 如果你想保護 API,有許多更好的作法,例如: diff --git a/docs/zh-hant/docs/how-to/configure-swagger-ui.md b/docs/zh-hant/docs/how-to/configure-swagger-ui.md index e5b6d7d1e3..cbb63ef5e6 100644 --- a/docs/zh-hant/docs/how-to/configure-swagger-ui.md +++ b/docs/zh-hant/docs/how-to/configure-swagger-ui.md @@ -1,12 +1,12 @@ # 設定 Swagger UI { #configure-swagger-ui } -你可以設定一些額外的 Swagger UI 參數。 +你可以設定一些額外的 [Swagger UI 參數](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/)。 要設定它們,建立 `FastAPI()` 應用物件時,或呼叫 `get_swagger_ui_html()` 函式時,傳入參數 `swagger_ui_parameters`。 `swagger_ui_parameters` 接受一個 dict,內容會直接傳給 Swagger UI 作為設定。 -FastAPI 會把這些設定轉換成 JSON,以便與 JavaScript 相容,因為 Swagger UI 需要的是這種格式。 +FastAPI 會把這些設定轉換成 **JSON**,以便與 JavaScript 相容,因為 Swagger UI 需要的是這種格式。 ## 停用語法醒目提示 { #disable-syntax-highlighting } @@ -50,11 +50,11 @@ FastAPI 內建一些預設參數,適用於大多數情境。 ## 其他 Swagger UI 參數 { #other-swagger-ui-parameters } -若要查看所有可用的設定,請參考官方的 Swagger UI 參數文件。 +若要查看所有可用的設定,請參考官方的 [Swagger UI 參數文件](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/)。 ## 僅限 JavaScript 的設定 { #javascript-only-settings } -Swagger UI 也允許某些設定是僅限 JavaScript 的物件(例如 JavaScript 函式)。 +Swagger UI 也允許某些設定是**僅限 JavaScript** 的物件(例如 JavaScript 函式)。 FastAPI 也包含以下僅限 JavaScript 的 `presets` 設定: diff --git a/docs/zh-hant/docs/how-to/custom-docs-ui-assets.md b/docs/zh-hant/docs/how-to/custom-docs-ui-assets.md index 4b53945891..e690e55c96 100644 --- a/docs/zh-hant/docs/how-to/custom-docs-ui-assets.md +++ b/docs/zh-hant/docs/how-to/custom-docs-ui-assets.md @@ -54,7 +54,7 @@ Swagger UI 會在背後幫你處理,不過它需要這個「redirect」輔助 ### 測試 { #test-it } -現在你應該能造訪 http://127.0.0.1:8000/docs,重新載入頁面後,資源會從新的 CDN 載入。 +現在你應該能造訪 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs),重新載入頁面後,資源會從新的 CDN 載入。 ## 自行託管文件所需的 JavaScript 與 CSS { #self-hosting-javascript-and-css-for-docs } @@ -93,12 +93,12 @@ Swagger UI 會在背後幫你處理,不過它需要這個「redirect」輔助 Swagger UI 需要以下檔案: -* `swagger-ui-bundle.js` -* `swagger-ui.css` +* [`swagger-ui-bundle.js`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js) +* [`swagger-ui.css`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css) 而 ReDoc 需要以下檔案: -* `redoc.standalone.js` +* [`redoc.standalone.js`](https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js) 之後,你的檔案結構可能如下: @@ -122,7 +122,7 @@ Swagger UI 需要以下檔案: ### 測試靜態檔案 { #test-the-static-files } -啟動你的應用並前往 http://127.0.0.1:8000/static/redoc.standalone.js。 +啟動你的應用並前往 [http://127.0.0.1:8000/static/redoc.standalone.js](http://127.0.0.1:8000/static/redoc.standalone.js)。 你應該會看到一個很長的 **ReDoc** JavaScript 檔案。 @@ -180,6 +180,6 @@ Swagger UI 會在背後幫你處理,不過它需要這個「redirect」輔助 ### 測試使用靜態檔案的 UI { #test-static-files-ui } -現在,你應該可以關閉 WiFi,造訪你的文件 http://127.0.0.1:8000/docs,並重新載入頁面。 +現在,你應該可以關閉 WiFi,造訪你的文件 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs),並重新載入頁面。 即使沒有網際網路,也能看到你的 API 文件並與之互動。 diff --git a/docs/zh-hant/docs/how-to/custom-request-and-route.md b/docs/zh-hant/docs/how-to/custom-request-and-route.md index 99c3410e47..00031fcaad 100644 --- a/docs/zh-hant/docs/how-to/custom-request-and-route.md +++ b/docs/zh-hant/docs/how-to/custom-request-and-route.md @@ -18,7 +18,7 @@ 可能的使用情境包括: -* 將非 JSON 的請求本文轉換為 JSON(例如 `msgpack`)。 +* 將非 JSON 的請求本文轉換為 JSON(例如 [`msgpack`](https://msgpack.org/index.html))。 * 解壓縮以 gzip 壓縮的請求本文。 * 自動記錄所有請求本文。 @@ -32,7 +32,7 @@ /// tip -這是一個示範用的簡化範例;如果你需要 Gzip 支援,可以直接使用提供的 [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank}。 +這是一個示範用的簡化範例;如果你需要 Gzip 支援,可以直接使用提供的 [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware)。 /// @@ -40,7 +40,7 @@ 如果標頭中沒有 `gzip`,它就不會嘗試解壓縮本文。 -如此一來,相同的路由類別即可同時處理經 gzip 壓縮與未壓縮的請求. +如此一來,相同的路由類別即可同時處理經 gzip 壓縮與未壓縮的請求。 {* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *} @@ -66,7 +66,7 @@ 而 `scope` 與 `receive` 這兩者,就是建立一個新的 `Request` 實例所需的資料。 -想了解更多 `Request`,請參考 Starlette 的 Request 文件。 +想了解更多 `Request`,請參考 [Starlette 的 Request 文件](https://www.starlette.dev/requests/)。 /// @@ -82,7 +82,7 @@ /// tip -要解決相同問題,使用針對 `RequestValidationError` 的自訂處理器來讀取 `body` 通常更簡單([處理錯誤](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank})。 +要解決相同問題,使用針對 `RequestValidationError` 的自訂處理器來讀取 `body` 通常更簡單([處理錯誤](../tutorial/handling-errors.md#use-the-requestvalidationerror-body))。 但本範例仍然有效,並示範了如何與內部元件互動。 diff --git a/docs/zh-hant/docs/how-to/extending-openapi.md b/docs/zh-hant/docs/how-to/extending-openapi.md index c51e896f32..b5adca0f76 100644 --- a/docs/zh-hant/docs/how-to/extending-openapi.md +++ b/docs/zh-hant/docs/how-to/extending-openapi.md @@ -37,7 +37,7 @@ 基於上述資訊,你可以用相同的工具函式來產生 OpenAPI 結構,並覆寫你需要客製的部分。 -例如,我們要加入 ReDoc 的 OpenAPI 擴充,插入自訂 logo。 +例如,我們要加入 [ReDoc 的 OpenAPI 擴充,插入自訂 logo](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo)。 ### 一般的 **FastAPI** { #normal-fastapi } @@ -75,6 +75,6 @@ ### 檢查看看 { #check-it } -造訪 http://127.0.0.1:8000/redoc 後,你會看到自訂的 logo(此例為 **FastAPI** 的 logo): +造訪 [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) 後,你會看到自訂的 logo(此例為 **FastAPI** 的 logo): diff --git a/docs/zh-hant/docs/how-to/general.md b/docs/zh-hant/docs/how-to/general.md index 96a71d62dd..13d4d7d3ee 100644 --- a/docs/zh-hant/docs/how-to/general.md +++ b/docs/zh-hant/docs/how-to/general.md @@ -4,36 +4,40 @@ ## 篩選資料 - 安全性 { #filter-data-security } -為確保你不會回傳超出應有的資料,請參閱[教學 - 回應模型 - 回傳型別](../tutorial/response-model.md){.internal-link target=_blank}。 +為確保你不會回傳超出應有的資料,請參閱[教學 - 回應模型 - 回傳型別](../tutorial/response-model.md)。 + +## 最佳化回應效能 - 回應模型 - 回傳型別 { #optimize-response-performance-response-model-return-type } + +為了在回傳 JSON 資料時最佳化效能,請使用回傳型別或回應模型,如此 Pydantic 會在 Rust 端處理序列化為 JSON,而不經過 Python。更多內容請參閱[教學 - 回應模型 - 回傳型別](../tutorial/response-model.md)。 ## 文件標籤 - OpenAPI { #documentation-tags-openapi } -要在你的*路徑操作(path operation)*加入標籤,並在文件 UI 中分組,請參閱[教學 - 路徑操作設定 - 標籤](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank}。 +要在你的*路徑操作(path operation)*加入標籤,並在文件 UI 中分組,請參閱[教學 - 路徑操作設定 - 標籤](../tutorial/path-operation-configuration.md#tags)。 ## 文件摘要與描述 - OpenAPI { #documentation-summary-and-description-openapi } -要為你的*路徑操作*加入摘要與描述,並在文件 UI 中顯示,請參閱[教學 - 路徑操作設定 - 摘要與描述](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank}。 +要為你的*路徑操作*加入摘要與描述,並在文件 UI 中顯示,請參閱[教學 - 路徑操作設定 - 摘要與描述](../tutorial/path-operation-configuration.md#summary-and-description)。 ## 文件回應描述 - OpenAPI { #documentation-response-description-openapi } -要定義在文件 UI 中顯示的回應描述,請參閱[教學 - 路徑操作設定 - 回應描述](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank}。 +要定義在文件 UI 中顯示的回應描述,請參閱[教學 - 路徑操作設定 - 回應描述](../tutorial/path-operation-configuration.md#response-description)。 ## 文件將*路徑操作*標記為已棄用 - OpenAPI { #documentation-deprecate-a-path-operation-openapi } -要將*路徑操作*標記為已棄用,並在文件 UI 中顯示,請參閱[教學 - 路徑操作設定 - 棄用](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank}。 +要將*路徑操作*標記為已棄用,並在文件 UI 中顯示,請參閱[教學 - 路徑操作設定 - 棄用](../tutorial/path-operation-configuration.md#deprecate-a-path-operation)。 ## 將任意資料轉換為 JSON 相容格式 { #convert-any-data-to-json-compatible } -要將任意資料轉換為 JSON 相容格式,請參閱[教學 - JSON 相容編碼器](../tutorial/encoder.md){.internal-link target=_blank}。 +要將任意資料轉換為 JSON 相容格式,請參閱[教學 - JSON 相容編碼器](../tutorial/encoder.md)。 ## OpenAPI 中繼資料 - 文件 { #openapi-metadata-docs } -要在你的 OpenAPI 綱要中加入中繼資料(包含授權、版本、聯絡方式等),請參閱[教學 - 中繼資料與文件 URL](../tutorial/metadata.md){.internal-link target=_blank}。 +要在你的 OpenAPI 綱要中加入中繼資料(包含授權、版本、聯絡方式等),請參閱[教學 - 中繼資料與文件 URL](../tutorial/metadata.md)。 ## 自訂 OpenAPI URL { #openapi-custom-url } -要自訂(或移除)OpenAPI 的 URL,請參閱[教學 - 中繼資料與文件 URL](../tutorial/metadata.md#openapi-url){.internal-link target=_blank}。 +要自訂(或移除)OpenAPI 的 URL,請參閱[教學 - 中繼資料與文件 URL](../tutorial/metadata.md#openapi-url)。 ## OpenAPI 文件 URL { #openapi-docs-urls } -要更新自動產生的文件使用者介面所使用的 URL,請參閱[教學 - 中繼資料與文件 URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}。 +要更新自動產生的文件使用者介面所使用的 URL,請參閱[教學 - 中繼資料與文件 URL](../tutorial/metadata.md#docs-urls)。 diff --git a/docs/zh-hant/docs/how-to/graphql.md b/docs/zh-hant/docs/how-to/graphql.md index 51933210c5..24e4d89792 100644 --- a/docs/zh-hant/docs/how-to/graphql.md +++ b/docs/zh-hant/docs/how-to/graphql.md @@ -18,18 +18,18 @@ GraphQL 解決某些非常特定的使用情境。 下面是支援 ASGI 的部分 GraphQL 函式庫,你可以與 FastAPI 一起使用: -* Strawberry 🍓 - * 提供 FastAPI 文件 -* Ariadne - * 提供 FastAPI 文件 -* Tartiflette - * 使用 Tartiflette ASGI 提供 ASGI 整合 -* Graphene - * 搭配 starlette-graphene3 +* [Strawberry](https://strawberry.rocks/) 🍓 + * 提供 [FastAPI 文件](https://strawberry.rocks/docs/integrations/fastapi) +* [Ariadne](https://ariadnegraphql.org/) + * 提供 [FastAPI 文件](https://ariadnegraphql.org/docs/fastapi-integration) +* [Tartiflette](https://tartiflette.io/) + * 使用 [Tartiflette ASGI](https://tartiflette.github.io/tartiflette-asgi/) 提供 ASGI 整合 +* [Graphene](https://graphene-python.org/) + * 搭配 [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3) ## 使用 Strawberry 的 GraphQL { #graphql-with-strawberry } -如果你需要或想使用 GraphQL,Strawberry 是推薦的函式庫,因為它的設計與 FastAPI 最接近,全部都基於型別註解 (type annotations)。 +如果你需要或想使用 GraphQL,[Strawberry](https://strawberry.rocks/) 是推薦的函式庫,因為它的設計與 FastAPI 最接近,全部都基於型別註解 (type annotations)。 視你的使用情境而定,你可能會偏好其他函式庫,但如果你問我,我大概會建議你先試試 Strawberry。 @@ -37,24 +37,24 @@ GraphQL 解決某些非常特定的使用情境。 {* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} -你可以在 Strawberry 文件 中進一步了解 Strawberry。 +你可以在 [Strawberry 文件](https://strawberry.rocks/) 中進一步了解 Strawberry。 -也可以參考關於 Strawberry 與 FastAPI 的文件。 +也可以參考關於 [Strawberry 與 FastAPI](https://strawberry.rocks/docs/integrations/fastapi) 的文件。 ## 來自 Starlette 的較舊 `GraphQLApp` { #older-graphqlapp-from-starlette } -早期版本的 Starlette 提供 `GraphQLApp` 類別以整合 Graphene。 +早期版本的 Starlette 提供 `GraphQLApp` 類別以整合 [Graphene](https://graphene-python.org/)。 -它已在 Starlette 中被棄用,但如果你的程式碼使用了它,可以輕鬆遷移到 starlette-graphene3,涵蓋相同的使用情境,且介面幾乎相同。 +它已在 Starlette 中被棄用,但如果你的程式碼使用了它,可以輕鬆遷移到 [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3),涵蓋相同的使用情境,且介面幾乎相同。 /// tip -如果你需要 GraphQL,我仍建議你看看 Strawberry,因為它基於型別註解,而不是自訂的類別與型別。 +如果你需要 GraphQL,我仍建議你看看 [Strawberry](https://strawberry.rocks/),因為它基於型別註解,而不是自訂的類別與型別。 /// ## 進一步了解 { #learn-more } -你可以在 官方 GraphQL 文件 中進一步了解 GraphQL。 +你可以在 [官方 GraphQL 文件](https://graphql.org/) 中進一步了解 GraphQL。 你也可以透過上述連結閱讀各個函式庫的更多內容。 diff --git a/docs/zh-hant/docs/how-to/index.md b/docs/zh-hant/docs/how-to/index.md index 6c9a8202c0..c08bd3d663 100644 --- a/docs/zh-hant/docs/how-to/index.md +++ b/docs/zh-hant/docs/how-to/index.md @@ -8,6 +8,6 @@ /// tip -如果你想要以結構化的方式**學習 FastAPI**(推薦),請前往[教學 - 使用者指南](../tutorial/index.md){.internal-link target=_blank}逐章閱讀。 +如果你想要以結構化的方式**學習 FastAPI**(推薦),請前往[教學 - 使用者指南](../tutorial/index.md)逐章閱讀。 /// diff --git a/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 109e57bc81..4495e3dd70 100644 --- a/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -22,7 +22,7 @@ Pydantic 團隊自 **Python 3.14** 起,已停止在最新的 Python 版本中 ## 官方指南 { #official-guide } -Pydantic 提供從 v1 遷移到 v2 的官方遷移指南。 +Pydantic 提供從 v1 遷移到 v2 的官方[遷移指南](https://docs.pydantic.dev/latest/migration/)。 其中包含變更內容、驗證如何更正確且更嚴格、可能的注意事項等。 @@ -30,7 +30,7 @@ Pydantic 提供從 v1 遷移到 v2 的官方`bump-pydantic`。 +你可以使用 Pydantic 團隊提供的 [`bump-pydantic`](https://github.com/pydantic/bump-pydantic)。 這個工具會自動修改大部分需要變更的程式碼。 diff --git a/docs/zh-hant/docs/how-to/testing-database.md b/docs/zh-hant/docs/how-to/testing-database.md index cbaecc2389..cf1ed9d36a 100644 --- a/docs/zh-hant/docs/how-to/testing-database.md +++ b/docs/zh-hant/docs/how-to/testing-database.md @@ -1,7 +1,7 @@ # 測試資料庫 { #testing-a-database } -你可以在 SQLModel 文件 中學習關於資料庫、SQL 與 SQLModel。 🤓 +你可以在 [SQLModel 文件](https://sqlmodel.tiangolo.com/) 中學習關於資料庫、SQL 與 SQLModel。 🤓 -有一個迷你 將 SQLModel 與 FastAPI 搭配使用的教學。 ✨ +有一個迷你 [將 SQLModel 與 FastAPI 搭配使用的教學](https://sqlmodel.tiangolo.com/tutorial/fastapi/)。 ✨ -該教學包含一節介紹 測試 SQL 資料庫。 😎 +該教學包含一節介紹 [測試 SQL 資料庫](https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/)。 😎 diff --git a/docs/zh-hant/docs/index.md b/docs/zh-hant/docs/index.md index 77eba9b149..d57791bf8b 100644 --- a/docs/zh-hant/docs/index.md +++ b/docs/zh-hant/docs/index.md @@ -11,25 +11,25 @@ FastAPI 框架,高效能,易於學習,快速開發,適用於生產環境

- + Test - + Coverage - + Package version - + Supported Python versions

--- -**文件**: https://fastapi.tiangolo.com/zh-hant +**文件**: [https://fastapi.tiangolo.com/zh-hant](https://fastapi.tiangolo.com/zh-hant) -**程式碼**: https://github.com/fastapi/fastapi +**程式碼**: [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi) --- @@ -44,7 +44,7 @@ FastAPI 是一個現代、快速(高效能)的 Web 框架,用於以 Python * **簡單**:設計上易於使用與學習。更少的讀文件時間。 * **簡潔**:最小化程式碼重複性。每個參數宣告可帶來多個功能。更少的錯誤。 * **穩健**:立即獲得可投入生產的程式碼,並自動生成互動式文件。 -* **標準化**:基於(且完全相容於)API 的開放標準:OpenAPI(之前稱為 Swagger)和 JSON Schema。 +* **標準化**:基於(且完全相容於)API 的開放標準:[OpenAPI](https://github.com/OAI/OpenAPI-Specification)(之前稱為 Swagger)和 [JSON Schema](https://json-schema.org/)。 * 基於內部開發團隊在建立生產應用程式時的測試預估。 @@ -55,51 +55,51 @@ FastAPI 是一個現代、快速(高效能)的 Web 框架,用於以 Python ### 基石贊助商 { #keystone-sponsor } {% for sponsor in sponsors.keystone -%} - + {% endfor -%} ### 金級與銀級贊助商 { #gold-and-silver-sponsors } {% for sponsor in sponsors.gold -%} - + {% endfor -%} {%- for sponsor in sponsors.silver -%} - + {% endfor %} -其他贊助商 +[其他贊助商](https://fastapi.tiangolo.com/zh-hant/fastapi-people/#sponsors) ## 評價 { #opinions } "_[...] 近期大量使用 **FastAPI**。[...] 我實際上打算在我在**微軟**團隊的所有**機器學習**服務上使用它。其中一些正在整合到核心的 **Windows** 產品,以及一些 **Office** 產品。_" -
Kabir Khan - Microsoft (ref)
+
Kabir Khan - Microsoft (ref)
--- "_我們採用了 **FastAPI** 函式庫來啟動一個 **REST** 伺服器,供查詢以取得**預測**。[for Ludwig]_" -
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
+
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
--- "_**Netflix** 很高興宣布我們的**危機管理**協調框架 **Dispatch** 開源![使用 **FastAPI** 建構]_" -
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
+
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
--- "_我對 **FastAPI** 興奮得不得了。超好玩!_" -
Brian Okken - Python Bytes podcast 主持人 (ref)
+
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) podcast 主持人 (ref)
--- "_老實說,你們做的看起來非常穩健又精緻。很多方面都正是我希望 **Hug** 成為的樣子——看到有人把它建出來真的很鼓舞人心。_" -
Timothy Crosley - Hug 創作者 (ref)
+
Timothy Crosley - [Hug](https://github.com/hugapi/hug) 創作者 (ref)
--- @@ -107,27 +107,27 @@ FastAPI 是一個現代、快速(高效能)的 Web 框架,用於以 Python "_我們的 **API** 已經改用 **FastAPI** [...] 我想你會喜歡它 [...]_" -
Ines Montani - Matthew Honnibal - Explosion AI 創辦人 - spaCy 創作者 (ref) - (ref)
+
Ines Montani - Matthew Honnibal - [Explosion AI](https://explosion.ai) 創辦人 - [spaCy](https://spacy.io) 創作者 (ref) - (ref)
--- -"_如果有人想要建立一個可投入生產的 Python API,我強烈推薦 **FastAPI**。它**設計精美**、**使用簡單**且**高度可擴充**,已成為我們 API 優先開發策略中的**關鍵組件**,推動了許多自動化與服務,例如我們的 Virtual TAC Engineer。_" +"_如果有人想要打造一個可用於生產環境的 Python API,我強力推薦 **FastAPI**。它**設計優雅**、**簡單易用**且**高度可擴展**,已經成為我們 API first 開發策略中的**關鍵元件**,推動了許多自動化與服務,例如我們的 Virtual TAC Engineer。_" -
Deon Pillsbury - Cisco (ref)
+
Deon Pillsbury - Cisco (ref)
--- ## FastAPI 迷你紀錄片 { #fastapi-mini-documentary } -在 2025 年底發布了一支 FastAPI 迷你紀錄片,你可以在線上觀看: +在 2025 年底發布了一支 [FastAPI 迷你紀錄片](https://www.youtube.com/watch?v=mpR8ngthqiE),你可以在線上觀看: -FastAPI Mini Documentary +FastAPI Mini Documentary ## **Typer**,命令列的 FastAPI { #typer-the-fastapi-of-clis } - + -如果你不是在做 Web API,而是要建立一個在終端機中使用的 CLI 應用程式,可以看看 **Typer**。 +如果你不是在做 Web API,而是要建立一個在終端機中使用的 CLI 應用程式,可以看看 [**Typer**](https://typer.tiangolo.com/)。 **Typer** 是 FastAPI 的小老弟。他立志成為命令列世界的 **FastAPI**。⌨️ 🚀 @@ -135,12 +135,12 @@ FastAPI 是一個現代、快速(高效能)的 Web 框架,用於以 Python FastAPI 是站在以下巨人的肩膀上: -* Starlette 負責 Web 部分。 -* Pydantic 負責資料部分。 +* [Starlette](https://www.starlette.dev/) 負責 Web 部分。 +* [Pydantic](https://docs.pydantic.dev/) 負責資料部分。 ## 安裝 { #installation } -建立並啟用一個虛擬環境,然後安裝 FastAPI: +建立並啟用一個[虛擬環境](https://fastapi.tiangolo.com/zh-hant/virtual-environments/),然後安裝 FastAPI:
@@ -199,7 +199,7 @@ async def read_item(item_id: int, q: str | None = None): **注意**: -如果你不確定,請查看文件中 _"In a hurry?"_ 章節的 `async` 與 `await`。 +如果你不確定,請查看文件中 _"In a hurry?"_ 章節的[關於文件中的 `async` 與 `await`](https://fastapi.tiangolo.com/zh-hant/async/#in-a-hurry)。 @@ -210,7 +210,7 @@ async def read_item(item_id: int, q: str | None = None):
```console -$ fastapi dev main.py +$ fastapi dev ╭────────── FastAPI CLI - Development mode ───────────╮ │ │ @@ -235,19 +235,19 @@ INFO: Application startup complete.
-關於指令 fastapi dev main.py... +關於指令 fastapi dev... -指令 `fastapi dev` 會讀取你的 `main.py`,偵測其中的 **FastAPI** 應用,並使用 Uvicorn 啟動伺服器。 +指令 `fastapi dev` 會讀取你的 `main.py`,偵測其中的 **FastAPI** 應用,並使用 [Uvicorn](https://www.uvicorn.dev) 啟動伺服器。 預設情況下,`fastapi dev` 會在本機開發時啟用自動重新載入。 -可在 FastAPI CLI 文件中閱讀更多資訊。 +可在 [FastAPI CLI 文件](https://fastapi.tiangolo.com/zh-hant/fastapi-cli/)中閱讀更多資訊。
### 檢查 { #check-it } -使用瀏覽器開啟 http://127.0.0.1:8000/items/5?q=somequery。 +使用瀏覽器開啟 [http://127.0.0.1:8000/items/5?q=somequery](http://127.0.0.1:8000/items/5?q=somequery)。 你將會看到以下 JSON 回應: @@ -264,17 +264,17 @@ INFO: Application startup complete. ### 互動式 API 文件 { #interactive-api-docs } -接著前往 http://127.0.0.1:8000/docs。 +接著前往 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 -你會看到自動生成的互動式 API 文件(由 Swagger UI 提供): +你會看到自動生成的互動式 API 文件(由 [Swagger UI](https://github.com/swagger-api/swagger-ui) 提供): ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) ### 替代 API 文件 { #alternative-api-docs } -現在前往 http://127.0.0.1:8000/redoc。 +現在前往 [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)。 -你會看到另一種自動文件(由 ReDoc 提供): +你會看到另一種自動文件(由 [ReDoc](https://github.com/Rebilly/ReDoc) 提供): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -316,7 +316,7 @@ def update_item(item_id: int, item: Item): ### 互動式 API 文件升級 { #interactive-api-docs-upgrade } -前往 http://127.0.0.1:8000/docs。 +前往 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 * 互動式 API 文件會自動更新,包含新的 body: @@ -332,7 +332,7 @@ def update_item(item_id: int, item: Item): ### 替代 API 文件升級 { #alternative-api-docs-upgrade } -現在前往 http://127.0.0.1:8000/redoc。 +現在前往 [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)。 * 替代文件也會反映新的查詢參數與 body: @@ -433,7 +433,7 @@ item: Item ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -若想看包含更多功能的完整範例,請參考 教學 - 使用者指南。 +若想看包含更多功能的完整範例,請參考 Tutorial - User Guide。 **劇透警告**:教學 - 使用者指南包含: @@ -442,7 +442,7 @@ item: Item * 一個非常強大且易用的 **依賴注入** 系統。 * 安全與驗證,包含支援 **OAuth2** 搭配 **JWT tokens** 與 **HTTP Basic** 驗證。 * 宣告**深度巢狀 JSON 模型**的進階(但同樣簡單)技巧(感謝 Pydantic)。 -* 與 Strawberry 及其他函式庫的 **GraphQL** 整合。 +* 與 [Strawberry](https://strawberry.rocks) 及其他函式庫的 **GraphQL** 整合。 * 許多額外功能(感謝 Starlette),例如: * **WebSockets** * 基於 HTTPX 與 `pytest` 的極其簡單的測試 @@ -452,24 +452,10 @@ item: Item ### 部署你的應用(可選) { #deploy-your-app-optional } -你也可以選擇將 FastAPI 應用部署到 FastAPI Cloud,如果你還沒加入,去登記等候名單吧。🚀 +你也可以選擇將 FastAPI 應用部署到 [FastAPI Cloud](https://fastapicloud.com),如果你還沒加入,去登記等候名單吧。🚀 如果你已經有 **FastAPI Cloud** 帳號(我們已從等候名單邀請你 😉),你可以用一個指令部署你的應用。 -部署前,先確認你已登入: - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -接著部署你的應用: -
```console @@ -488,7 +474,7 @@ Deploying to FastAPI Cloud... #### 關於 FastAPI Cloud { #about-fastapi-cloud } -**FastAPI Cloud** 由 **FastAPI** 的同一位作者與團隊打造。 +**[FastAPI Cloud](https://fastapicloud.com)** 由 **FastAPI** 的同一位作者與團隊打造。 它讓你以最小的努力精簡地完成 API 的**建置**、**部署**與**存取**流程。 @@ -504,9 +490,9 @@ FastAPI 是開源且基於標準。你可以把 FastAPI 應用部署到任何你 ## 效能 { #performance } -獨立的 TechEmpower 基準測試顯示,在 Uvicorn 下運行的 **FastAPI** 應用是最快的 Python 框架之一,僅次於 Starlette 與 Uvicorn 本身(FastAPI 內部使用它們)。(*) +獨立的 TechEmpower 基準測試顯示,在 Uvicorn 下運行的 **FastAPI** 應用是[最快的 Python 框架之一](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7),僅次於 Starlette 與 Uvicorn 本身(FastAPI 內部使用它們)。(*) -想了解更多,請參閱測試結果。 +想了解更多,請參閱[測試結果](https://fastapi.tiangolo.com/zh-hant/benchmarks/)。 ## 依賴套件 { #dependencies } @@ -518,19 +504,19 @@ FastAPI 依賴 Pydantic 與 Starlette。 Pydantic 會使用: -* email-validator - 用於電子郵件驗證。 +* [`email-validator`](https://github.com/JoshData/python-email-validator) - 用於電子郵件驗證。 Starlette 會使用: -* httpx - 若要使用 `TestClient` 必須安裝。 -* jinja2 - 若要使用預設的模板設定必須安裝。 -* python-multipart - 若要支援表單 "解析",搭配 `request.form()`。 +* [`httpx`](https://www.python-httpx.org) - 若要使用 `TestClient` 必須安裝。 +* [`jinja2`](https://jinja.palletsprojects.com) - 若要使用預設的模板設定必須安裝。 +* [`python-multipart`](https://github.com/Kludex/python-multipart) - 若要支援表單 "解析",搭配 `request.form()`。 FastAPI 會使用: -* uvicorn - 用於載入並服務你的應用的伺服器。這包含 `uvicorn[standard]`,其中含有一些高效能服務所需的依賴(例如 `uvloop`)。 +* [`uvicorn`](https://www.uvicorn.dev) - 用於載入並服務你的應用的伺服器。這包含 `uvicorn[standard]`,其中含有一些高效能服務所需的依賴(例如 `uvloop`)。 * `fastapi-cli[standard]` - 提供 `fastapi` 指令。 - * 其中包含 `fastapi-cloud-cli`,可讓你將 FastAPI 應用部署到 FastAPI Cloud。 + * 其中包含 `fastapi-cloud-cli`,可讓你將 FastAPI 應用部署到 [FastAPI Cloud](https://fastapicloud.com)。 ### 不含 `standard` 依賴套件 { #without-standard-dependencies } @@ -546,13 +532,13 @@ FastAPI 會使用: Pydantic 的額外可選依賴: -* pydantic-settings - 設定管理。 -* pydantic-extra-types - 與 Pydantic 一起使用的額外型別。 +* [`pydantic-settings`](https://docs.pydantic.dev/latest/usage/pydantic_settings/) - 設定管理。 +* [`pydantic-extra-types`](https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/) - 與 Pydantic 一起使用的額外型別。 FastAPI 的額外可選依賴: -* orjson - 若要使用 `ORJSONResponse` 必須安裝。 -* ujson - 若要使用 `UJSONResponse` 必須安裝。 +* [`orjson`](https://github.com/ijl/orjson) - 若要使用 `ORJSONResponse` 必須安裝。 +* [`ujson`](https://github.com/esnme/ultrajson) - 若要使用 `UJSONResponse` 必須安裝。 ## 授權 { #license } diff --git a/docs/zh-hant/docs/project-generation.md b/docs/zh-hant/docs/project-generation.md index 7fa92ce558..fc5c8e4655 100644 --- a/docs/zh-hant/docs/project-generation.md +++ b/docs/zh-hant/docs/project-generation.md @@ -4,7 +4,7 @@ 你可以使用此範本快速起步,裡面已替你完成大量初始設定、安全性、資料庫,以及部分 API 端點。 -GitHub 儲存庫:全端 FastAPI 範本 +GitHub 儲存庫:[全端 FastAPI 範本](https://github.com/tiangolo/full-stack-fastapi-template) ## 全端 FastAPI 範本 - 技術堆疊與功能 { #full-stack-fastapi-template-technology-stack-and-features } diff --git a/docs/zh-hant/docs/python-types.md b/docs/zh-hant/docs/python-types.md index 4f498ab734..4193069ea7 100644 --- a/docs/zh-hant/docs/python-types.md +++ b/docs/zh-hant/docs/python-types.md @@ -269,7 +269,7 @@ def some_function(data: Any): ## Pydantic 模型 { #pydantic-models } -Pydantic 是一個用來做資料驗證的 Python 程式庫。 +[Pydantic](https://docs.pydantic.dev/) 是一個用來做資料驗證的 Python 程式庫。 你以帶有屬性的類別來宣告資料的「形狀」。 @@ -285,13 +285,13 @@ def some_function(data: Any): /// info | 資訊 -想了解更多 Pydantic,請查看它的文件。 +想了解更多 [Pydantic,請查看它的文件](https://docs.pydantic.dev/)。 /// **FastAPI** 完全是以 Pydantic 為基礎。 -你會在[教學 - 使用者指南](tutorial/index.md){.internal-link target=_blank}中看到更多實際範例。 +你會在[教學 - 使用者指南](tutorial/index.md)中看到更多實際範例。 ## 含中繼資料的型別提示 { #type-hints-with-metadata-annotations } @@ -337,12 +337,12 @@ Python 本身不會對這個 `Annotated` 做任何事。對編輯器與其他工 * 使用 OpenAPI 書寫 API 文件: * 之後會由自動的互動式文件介面所使用 -這些現在聽起來可能有點抽象。別擔心。你會在[教學 - 使用者指南](tutorial/index.md){.internal-link target=_blank}中看到它們的實際運作。 +這些現在聽起來可能有點抽象。別擔心。你會在[教學 - 使用者指南](tutorial/index.md)中看到它們的實際運作。 重點是,透過在單一位置使用標準的 Python 型別(而不是新增更多類別、裝飾器等),**FastAPI** 會幫你完成很多工作。 /// info | 資訊 -如果你已經完整讀完整個教學,並回來想多看一些關於型別的內容,一個不錯的資源是 `mypy` 的「小抄」。 +如果你已經完整讀完整個教學,並回來想多看一些關於型別的內容,一個不錯的資源是 [`mypy` 的「小抄」](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html)。 /// diff --git a/docs/zh-hant/docs/tutorial/background-tasks.md b/docs/zh-hant/docs/tutorial/background-tasks.md index 63e4e5a160..216ec88689 100644 --- a/docs/zh-hant/docs/tutorial/background-tasks.md +++ b/docs/zh-hant/docs/tutorial/background-tasks.md @@ -61,7 +61,7 @@ ## 技術細節 { #technical-details } -類別 `BackgroundTasks` 直接來自 `starlette.background`。 +類別 `BackgroundTasks` 直接來自 [`starlette.background`](https://www.starlette.dev/background/)。 它被直接匯入/包含到 FastAPI 中,因此你可以從 `fastapi` 匯入它,並避免不小心從 `starlette.background` 匯入另一個同名的 `BackgroundTask`(結尾沒有 s)。 @@ -69,11 +69,11 @@ 在 FastAPI 中仍可單獨使用 `BackgroundTask`,但你需要在程式碼中自行建立該物件,並回傳包含它的 Starlette `Response`。 -更多細節請參閱 Starlette 官方的 Background Tasks 文件。 +更多細節請參閱 [Starlette 官方的 Background Tasks 文件](https://www.starlette.dev/background/)。 ## 注意事項 { #caveat } -如果你需要執行繁重的背景計算,且不一定要由同一個行程執行(例如不需要共用記憶體、變數等),可以考慮使用更大型的工具,例如 Celery。 +如果你需要執行繁重的背景計算,且不一定要由同一個行程執行(例如不需要共用記憶體、變數等),可以考慮使用更大型的工具,例如 [Celery](https://docs.celeryq.dev)。 這類工具通常需要較複雜的設定,以及訊息/工作佇列管理器(如 RabbitMQ 或 Redis),但它們允許你在多個行程,甚至多台伺服器上執行背景任務。 diff --git a/docs/zh-hant/docs/tutorial/bigger-applications.md b/docs/zh-hant/docs/tutorial/bigger-applications.md index d8b8c9bff8..a37c16c39e 100644 --- a/docs/zh-hant/docs/tutorial/bigger-applications.md +++ b/docs/zh-hant/docs/tutorial/bigger-applications.md @@ -123,7 +123,7 @@ from app.routers import items 為了簡化範例,我們使用了一個虛構的標頭。 -但在真實情況下,使用內建的[安全工具](security/index.md){.internal-link target=_blank}會有更好的效果。 +但在真實情況下,使用內建的 [安全工具](security/index.md) 會有更好的效果。 /// @@ -169,7 +169,7 @@ async def read_item(item_id: str): /// tip | 提示 -請注意,就像在[路徑操作裝飾器中的相依性](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}一樣,不會把任何值傳遞給你的路徑操作函式(path operation function)。 +請注意,就像在[路徑操作裝飾器中的相依性](dependencies/dependencies-in-path-operation-decorators.md)一樣,不會把任何值傳遞給你的路徑操作函式(path operation function)。 /// @@ -185,8 +185,8 @@ async def read_item(item_id: str): * 它們都會包含預先定義的 `responses`。 * 這些路徑操作都會在執行前評估 / 執行其 `dependencies` 清單。 * 如果你也在特定的路徑操作中宣告了相依性,這些相依性也會被執行。 - * Router 的相依性會先執行,然後是[裝飾器中的 `dependencies`](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank},最後是一般參數相依性。 - * 你也可以加入帶有 `scopes` 的 [`Security` 相依性](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}。 + * Router 的相依性會先執行,然後是[裝飾器中的 `dependencies`](dependencies/dependencies-in-path-operation-decorators.md),最後是一般參數相依性。 + * 你也可以加入帶有 `scopes` 的 [`Security` 相依性](../advanced/security/oauth2-scopes.md)。 /// tip | 提示 @@ -303,7 +303,7 @@ from ...dependencies import get_token_header 照常匯入並建立 `FastAPI` 類別。 -我們甚至可以宣告[全域相依性](dependencies/global-dependencies.md){.internal-link target=_blank},它們會與各 `APIRouter` 的相依性合併: +我們甚至可以宣告[全域相依性](dependencies/global-dependencies.md),它們會與各 `APIRouter` 的相依性合併: {* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} @@ -353,7 +353,7 @@ from .routers import items, users from app.routers import items, users ``` -想了解更多關於 Python 套件與模組,請閱讀官方的模組說明文件。 +想了解更多關於 Python 套件與模組,請閱讀[官方的模組說明文件](https://docs.python.org/3/tutorial/modules.html)。 /// @@ -465,6 +465,37 @@ from .routers.users import router /// +## 在 `pyproject.toml` 設定 `entrypoint` { #configure-the-entrypoint-in-pyproject-toml } + +因為你的 FastAPI `app` 物件位在 `app/main.py`,你可以在 `pyproject.toml` 檔案中這樣設定 `entrypoint`: + +```toml +[tool.fastapi] +entrypoint = "app.main:app" +``` + +這等同於這樣匯入: + +```python +from app.main import app +``` + +如此一來 `fastapi` 指令就會知道去哪裡找到你的 app。 + +/// Note | 注意 + +你也可以把路徑直接傳給指令,例如: + +```console +$ fastapi dev app/main.py +``` + +但你每次呼叫 `fastapi` 指令時都得記得傳入正確的路徑。 + +此外,其他工具可能找不到它,例如 [VS Code 擴充套件](../editor-support.md) 或 [FastAPI Cloud](https://fastapicloud.com),因此建議在 `pyproject.toml` 中使用 `entrypoint`。 + +/// + ## 檢查自動產生的 API 文件 { #check-the-automatic-api-docs } 現在,執行你的應用: @@ -472,14 +503,14 @@ from .routers.users import router
```console -$ fastapi dev app/main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-然後開啟位於 http://127.0.0.1:8000/docs 的文件。 +然後開啟位於 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) 的文件。 你會看到自動產生的 API 文件,包含來自所有子模組的路徑,使用正確的路徑(與前綴)與正確的標籤: diff --git a/docs/zh-hant/docs/tutorial/body-nested-models.md b/docs/zh-hant/docs/tutorial/body-nested-models.md index df4aff6972..f7b8627b4b 100644 --- a/docs/zh-hant/docs/tutorial/body-nested-models.md +++ b/docs/zh-hant/docs/tutorial/body-nested-models.md @@ -95,7 +95,7 @@ my_list: list[str] 除了 `str`、`int`、`float` 等一般的單一型別外,你也可以使用繼承自 `str` 的更複雜單一型別。 -若要查看所有可用選項,請參閱 Pydantic 的型別總覽。你會在下一章看到一些範例。 +若要查看所有可用選項,請參閱 [Pydantic 的型別總覽](https://docs.pydantic.dev/latest/concepts/types/)。你會在下一章看到一些範例。 例如,在 `Image` 模型中有一個 `url` 欄位,我們可以將其宣告為 Pydantic 的 `HttpUrl`,而不是 `str`: diff --git a/docs/zh-hant/docs/tutorial/body-updates.md b/docs/zh-hant/docs/tutorial/body-updates.md index a309e3522c..0d48e28424 100644 --- a/docs/zh-hant/docs/tutorial/body-updates.md +++ b/docs/zh-hant/docs/tutorial/body-updates.md @@ -2,7 +2,7 @@ ## 使用 `PUT` 取代式更新 { #update-replacing-with-put } -要更新一個項目,你可以使用 HTTP `PUT` 操作。 +要更新一個項目,你可以使用 [HTTP `PUT`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) 操作。 你可以使用 `jsonable_encoder` 將輸入資料轉換為可儲存為 JSON 的資料(例如用於 NoSQL 資料庫)。例如把 `datetime` 轉成 `str`。 @@ -28,7 +28,7 @@ ## 使用 `PATCH` 進行部分更新 { #partial-updates-with-patch } -你也可以使用 HTTP `PATCH` 操作來進行*部分*更新。 +你也可以使用 [HTTP `PATCH`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) 操作來進行*部分*更新。 這表示你只需傳送想要更新的資料,其餘保持不變。 @@ -95,6 +95,6 @@ 因此,如果你希望接收可以省略所有屬性的部分更新,你需要一個所有屬性皆為可選(具預設值或為 `None`)的模型。 -為了區分用於更新(全部可選)與用於建立(欄位為必填)的模型,你可以參考 [額外模型](extra-models.md){.internal-link target=_blank} 中的做法。 +為了區分用於更新(全部可選)與用於建立(欄位為必填)的模型,你可以參考 [額外模型](extra-models.md) 中的做法。 /// diff --git a/docs/zh-hant/docs/tutorial/body.md b/docs/zh-hant/docs/tutorial/body.md index bddcbbf434..08246f513b 100644 --- a/docs/zh-hant/docs/tutorial/body.md +++ b/docs/zh-hant/docs/tutorial/body.md @@ -6,7 +6,7 @@ 你的 API 幾乎總是需要傳回**回應**本文。但用戶端不一定每次都要送出**請求本文**,有時只會請求某個路徑,可能帶一些查詢參數,但不會傳送本文。 -要宣告**請求**本文,你會使用 Pydantic 模型,享受其完整的功能與優點。 +要宣告**請求**本文,你會使用 [Pydantic](https://docs.pydantic.dev/) 模型,享受其完整的功能與優點。 /// info @@ -72,7 +72,7 @@ - 若資料無效,會回傳清楚易懂的錯誤,指出哪裡、哪筆資料不正確。 - 把接收到的資料放在參數 `item` 中提供給你。 - 由於你在函式中將其宣告為 `Item` 型別,你也會獲得完整的編輯器支援(自動完成等)以及所有屬性與其型別。 -- 為你的模型產生 JSON Schema 定義,如有需要,你也可以在專案中的其他地方使用。 +- 為你的模型產生 [JSON Schema](https://json-schema.org) 定義,如有需要,你也可以在專案中的其他地方使用。 - 這些 schema 會成為產生的 OpenAPI schema 的一部分,並由自動文件 UIs 使用。 ## 自動文件 { #automatic-docs } @@ -101,15 +101,15 @@ 甚至為了支援這點,Pydantic 本身也做了些修改。 -前面的螢幕截圖是使用 Visual Studio Code 拍的。 +前面的螢幕截圖是使用 [Visual Studio Code](https://code.visualstudio.com) 拍的。 -但你在 PyCharm 與大多數其它 Python 編輯器中也會得到相同的編輯器支援: +但你在 [PyCharm](https://www.jetbrains.com/pycharm/) 與大多數其它 Python 編輯器中也會得到相同的編輯器支援: /// tip -如果你使用 PyCharm 作為編輯器,可以安裝 Pydantic PyCharm Plugin。 +如果你使用 [PyCharm](https://www.jetbrains.com/pycharm/) 作為編輯器,可以安裝 [Pydantic PyCharm Plugin](https://github.com/koxudaxi/pydantic-pycharm-plugin/)。 它能增強 Pydantic 模型的編輯器支援,包含: @@ -161,4 +161,4 @@ FastAPI 會因為預設值 `= None` 而知道 `q` 的值不是必填。 ## 不使用 Pydantic { #without-pydantic } -若你不想使用 Pydantic 模型,也可以使用 **Body** 參數。請參考[Body - 多個參數:本文中的單一值](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}。 +若你不想使用 Pydantic 模型,也可以使用 **Body** 參數。請參考[Body - 多個參數:本文中的單一值](body-multiple-params.md#singular-values-in-body)。 diff --git a/docs/zh-hant/docs/tutorial/cors.md b/docs/zh-hant/docs/tutorial/cors.md index 5fa497c081..4fcf9f9418 100644 --- a/docs/zh-hant/docs/tutorial/cors.md +++ b/docs/zh-hant/docs/tutorial/cors.md @@ -1,6 +1,6 @@ # CORS(跨來源資源共用) { #cors-cross-origin-resource-sharing } -CORS 或「Cross-Origin Resource Sharing」指的是:當在瀏覽器中執行的前端以 JavaScript 與後端通訊,而後端與前端位於不同「來源(origin)」時的情境。 +[CORS 或「Cross-Origin Resource Sharing」](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)指的是:當在瀏覽器中執行的前端以 JavaScript 與後端通訊,而後端與前端位於不同「來源(origin)」時的情境。 ## 來源(Origin) { #origin } @@ -55,10 +55,10 @@ * `allow_origins` - 允許進行跨來源請求的來源清單。例如 `['https://example.org', 'https://www.example.org']`。你可以使用 `['*']` 來允許任何來源。 * `allow_origin_regex` - 允許進行跨來源請求的來源,使用正規表示式字串比對。例如 `'https://.*\.example\.org'`。 * `allow_methods` - 允許跨來源請求的 HTTP 方法清單。預設為 `['GET']`。你可以使用 `['*']` 來允許所有標準方法。 -* `allow_headers` - 允許跨來源請求所支援的 HTTP 請求標頭清單。預設為 `[]`。你可以使用 `['*']` 來允許所有標頭。對於簡單 CORS 請求,`Accept`、`Accept-Language`、`Content-Language` 與 `Content-Type` 標頭一律被允許。 +* `allow_headers` - 允許跨來源請求所支援的 HTTP 請求標頭清單。預設為 `[]`。你可以使用 `['*']` 來允許所有標頭。對於[簡單 CORS 請求](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests),`Accept`、`Accept-Language`、`Content-Language` 與 `Content-Type` 標頭一律被允許。 * `allow_credentials` - 指示是否支援跨來源請求的 Cookie。預設為 `False`。 - 當 `allow_credentials` 設為 `True` 時,`allow_origins`、`allow_methods` 與 `allow_headers` 都不能設為 `['*']`。上述各項必須明確指定。 + 當 `allow_credentials` 設為 `True` 時,`allow_origins`、`allow_methods` 與 `allow_headers` 都不能設為 `['*']`。上述各項必須[明確指定](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards)。 * `expose_headers` - 指示哪些回應標頭應該讓瀏覽器可存取。預設為 `[]`。 * `max_age` - 設定瀏覽器快取 CORS 回應的最長秒數。預設為 `600`。 @@ -77,7 +77,7 @@ ## 更多資訊 { #more-info } -想進一步了解 CORS,請參考 Mozilla 的 CORS 文件。 +想進一步了解 CORS,請參考 [Mozilla 的 CORS 文件](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)。 /// note | 技術細節 diff --git a/docs/zh-hant/docs/tutorial/debugging.md b/docs/zh-hant/docs/tutorial/debugging.md index cb82ee417b..1230ed6ccd 100644 --- a/docs/zh-hant/docs/tutorial/debugging.md +++ b/docs/zh-hant/docs/tutorial/debugging.md @@ -59,7 +59,7 @@ $ python myapp.py ```Python from myapp import app -# Some more code +# 其他程式碼 ``` 在那種情況下,`myapp.py` 中自動建立的變數 `__name__` 就不會是 `"__main__"`。 @@ -74,7 +74,7 @@ from myapp import app /// info | 說明 -想了解更多,參考 Python 官方文件。 +想了解更多,參考 [Python 官方文件](https://docs.python.org/3/library/__main__.html)。 /// diff --git a/docs/zh-hant/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/zh-hant/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index e30c385375..bd57116245 100644 --- a/docs/zh-hant/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/zh-hant/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -32,7 +32,7 @@ 在這個範例中我們使用了自訂的(虛構的)標頭 `X-Key` 與 `X-Token`。 -但在實際情況下,當你實作安全機制時,使用整合的 [Security utilities(下一章)](../security/index.md){.internal-link target=_blank} 會獲得更多好處。 +但在實際情況下,當你實作安全機制時,使用整合的 [Security utilities(下一章)](../security/index.md) 會獲得更多好處。 /// @@ -62,7 +62,7 @@ ## 一組路徑操作的依賴 { #dependencies-for-a-group-of-path-operations } -之後在閱讀如何組織較大的應用程式([較大型應用程式——多個檔案](../../tutorial/bigger-applications.md){.internal-link target=_blank})時,你會學到如何為一組路徑操作宣告一個共同的 `dependencies` 參數。 +之後在閱讀如何組織較大的應用程式([較大型應用程式——多個檔案](../../tutorial/bigger-applications.md))時,你會學到如何為一組路徑操作宣告一個共同的 `dependencies` 參數。 ## 全域依賴 { #global-dependencies } diff --git a/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md index 2339c6ef30..8174dca40b 100644 --- a/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md @@ -14,8 +14,8 @@ FastAPI 支援在完成後執行一些`@contextlib.contextmanager` 或 -* `@contextlib.asynccontextmanager` +* [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) 或 +* [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) 都可以作為 **FastAPI** 的相依。 @@ -87,7 +87,7 @@ FastAPI 支援在完成後執行一些Context Managers。 +這能運作,多虧了 Python 的 [Context Managers](https://docs.python.org/3/library/contextlib.html)。 **FastAPI** 在內部使用它們來達成這點。 @@ -111,7 +111,7 @@ FastAPI 支援在完成後執行一些你可以用 `with` 來讀取檔案: +例如,[你可以用 `with` 來讀取檔案](https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files): ```Python with open("./somefile.txt") as f: @@ -264,7 +264,7 @@ with open("./somefile.txt") as f: /// -在 Python 中,你可以透過建立一個擁有 `__enter__()` 與 `__exit__()` 兩個方法的類別來建立情境管理器。 +在 Python 中,你可以透過[建立一個擁有 `__enter__()` 與 `__exit__()` 兩個方法的類別](https://docs.python.org/3/reference/datamodel.html#context-managers)來建立情境管理器。 你也可以在 **FastAPI** 的含 `yield` 相依中,於相依函式內使用 `with` 或 `async with` 陳述式來使用它們: @@ -274,8 +274,8 @@ with open("./somefile.txt") as f: 建立情境管理器的另一種方式是: -* `@contextlib.contextmanager` 或 -* `@contextlib.asynccontextmanager` +* [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) 或 +* [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) 用它們裝飾一個只包含單一 `yield` 的函式。 diff --git a/docs/zh-hant/docs/tutorial/dependencies/global-dependencies.md b/docs/zh-hant/docs/tutorial/dependencies/global-dependencies.md index 3aac1a228b..e73cf935e2 100644 --- a/docs/zh-hant/docs/tutorial/dependencies/global-dependencies.md +++ b/docs/zh-hant/docs/tutorial/dependencies/global-dependencies.md @@ -2,14 +2,14 @@ 在某些類型的應用程式中,你可能想為整個應用程式新增依賴。 -類似於你可以在[路徑操作(path operation)的裝飾器中新增 `dependencies`](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} 的方式,你也可以把它們加到 `FastAPI` 應用程式上。 +類似於你可以在[路徑操作(path operation)的裝飾器中新增 `dependencies`](dependencies-in-path-operation-decorators.md) 的方式,你也可以把它們加到 `FastAPI` 應用程式上。 在這種情況下,它們會套用到應用程式中的所有路徑操作: {* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *} -而且,在[將 `dependencies` 新增到路徑操作裝飾器](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} 那一節中的所有概念依然適用,只是這裡是套用到整個應用中的所有路徑操作。 +而且,在[將 `dependencies` 新增到路徑操作裝飾器](dependencies-in-path-operation-decorators.md) 那一節中的所有概念依然適用,只是這裡是套用到整個應用中的所有路徑操作。 ## 路徑操作群組的依賴 { #dependencies-for-groups-of-path-operations } -之後,在閱讀如何組織更大的應用程式([更大的應用程式 - 多個檔案](../../tutorial/bigger-applications.md){.internal-link target=_blank})時,可能會有多個檔案,你將會學到如何為一組路徑操作宣告單一的 `dependencies` 參數。 +之後,在閱讀如何組織更大的應用程式([更大的應用程式 - 多個檔案](../../tutorial/bigger-applications.md))時,可能會有多個檔案,你將會學到如何為一組路徑操作宣告單一的 `dependencies` 參數。 diff --git a/docs/zh-hant/docs/tutorial/dependencies/index.md b/docs/zh-hant/docs/tutorial/dependencies/index.md index 39c05ab056..86aea50f0a 100644 --- a/docs/zh-hant/docs/tutorial/dependencies/index.md +++ b/docs/zh-hant/docs/tutorial/dependencies/index.md @@ -55,7 +55,7 @@ FastAPI 在 0.95.0 版新增了對 `Annotated` 的支援(並開始建議使用 如果你使用較舊的版本,嘗試使用 `Annotated` 時會出現錯誤。 -在使用 `Annotated` 之前,請先[升級 FastAPI 版本](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}到至少 0.95.1。 +在使用 `Annotated` 之前,請先[升級 FastAPI 版本](../../deployment/versions.md#upgrading-the-fastapi-versions)到至少 0.95.1。 /// @@ -150,7 +150,7 @@ commons: Annotated[dict, Depends(common_parameters)] /// note | 注意 -如果你不熟悉,請參考文件中的 [Async: "In a hurry?"](../../async.md#in-a-hurry){.internal-link target=_blank} 一節,瞭解 `async` 與 `await`。 +如果你不熟悉,請參考文件中的 [Async: "In a hurry?"](../../async.md#in-a-hurry) 一節,瞭解 `async` 與 `await`。 /// diff --git a/docs/zh-hant/docs/tutorial/encoder.md b/docs/zh-hant/docs/tutorial/encoder.md index 03b7db6394..9b541adce6 100644 --- a/docs/zh-hant/docs/tutorial/encoder.md +++ b/docs/zh-hant/docs/tutorial/encoder.md @@ -12,7 +12,7 @@ 例如,它不接受 `datetime` 物件,因為那與 JSON 不相容。 -因此,必須將 `datetime` 物件轉為一個以 ISO 格式 表示資料的 `str`。 +因此,必須將 `datetime` 物件轉為一個以 [ISO 格式](https://en.wikipedia.org/wiki/ISO_8601) 表示資料的 `str`。 同樣地,這個資料庫不會接受 Pydantic 模型(帶有屬性的物件),只接受 `dict`。 @@ -24,7 +24,7 @@ 在此範例中,它會把 Pydantic 模型轉成 `dict`,並將 `datetime` 轉成 `str`。 -呼叫後的結果可以用 Python 標準的 `json.dumps()` 進行編碼。 +呼叫後的結果可以用 Python 標準的 [`json.dumps()`](https://docs.python.org/3/library/json.html#json.dumps) 進行編碼。 它不會回傳一個包含 JSON 內容的大型 `str`(字串)。它會回傳 Python 標準的資料結構(例如 `dict`),其中的值與子值都與 JSON 相容。 diff --git a/docs/zh-hant/docs/tutorial/extra-data-types.md b/docs/zh-hant/docs/tutorial/extra-data-types.md index f516d965a4..a5573379d8 100644 --- a/docs/zh-hant/docs/tutorial/extra-data-types.md +++ b/docs/zh-hant/docs/tutorial/extra-data-types.md @@ -36,7 +36,7 @@ * `datetime.timedelta`: * Python 的 `datetime.timedelta`。 * 在請求與回應中會以總秒數的 `float` 表示。 - * Pydantic 也允許用「ISO 8601 time diff encoding」來表示,詳情見文件。 + * Pydantic 也允許用「ISO 8601 time diff encoding」來表示,[詳情見文件](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers)。 * `frozenset`: * 在請求與回應中與 `set` 相同處理: * 在請求中,會讀取一個 list,去除重複並轉為 `set`。 @@ -49,7 +49,7 @@ * `Decimal`: * 標準的 Python `Decimal`。 * 在請求與回應中,與 `float` 的處理方式相同。 -* 你可以在此查閱所有可用的 Pydantic 資料型別:Pydantic 資料型別。 +* 你可以在此查閱所有可用的 Pydantic 資料型別:[Pydantic 資料型別](https://docs.pydantic.dev/latest/usage/types/types/)。 ## 範例 { #example } diff --git a/docs/zh-hant/docs/tutorial/extra-models.md b/docs/zh-hant/docs/tutorial/extra-models.md index 8aae62f8e1..f5509f531f 100644 --- a/docs/zh-hant/docs/tutorial/extra-models.md +++ b/docs/zh-hant/docs/tutorial/extra-models.md @@ -12,7 +12,7 @@ 切勿儲存使用者的明文密碼。務必只儲存可供驗證的「安全雜湊」。 -若你還不清楚,稍後會在[安全性章節](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}學到什麼是「密碼雜湊」。 +若你還不清楚,稍後會在[安全性章節](security/simple-oauth2.md#password-hashing)學到什麼是「密碼雜湊」。 /// @@ -162,11 +162,11 @@ UserInDB( 在 OpenAPI 中會以 `anyOf` 定義。 -要達成這點,使用標準的 Python 型別提示 `typing.Union`: +要達成這點,使用標準的 Python 型別提示 [`typing.Union`](https://docs.python.org/3/library/typing.html#typing.Union): /// note -在定義 `Union` 時,請先放置「更具體」的型別,再放「較不具體」的型別。以下範例中,較具體的 `PlaneItem` 置於 `CarItem` 之前:`Union[PlaneItem, CarItem]`。 +在定義 [`Union`](https://docs.pydantic.dev/latest/concepts/types/#unions) 時,請先放置「更具體」的型別,再放「較不具體」的型別。以下範例中,較具體的 `PlaneItem` 置於 `CarItem` 之前:`Union[PlaneItem, CarItem]`。 /// diff --git a/docs/zh-hant/docs/tutorial/first-steps.md b/docs/zh-hant/docs/tutorial/first-steps.md index 3aa2d39ae1..d6b1a72e32 100644 --- a/docs/zh-hant/docs/tutorial/first-steps.md +++ b/docs/zh-hant/docs/tutorial/first-steps.md @@ -11,7 +11,7 @@
```console -$ fastapi dev main.py +$ fastapi dev FastAPI Starting development server 🚀 @@ -58,7 +58,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ### 查看它 { #check-it } -在瀏覽器中打開 http://127.0.0.1:8000. +在瀏覽器中打開 [http://127.0.0.1:8000](http://127.0.0.1:8000)。 你將看到如下的 JSON 回應: @@ -68,17 +68,17 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ### 互動式 API 文件 { #interactive-api-docs } -現在,前往 http://127.0.0.1:8000/docs. +現在,前往 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 -你將看到自動的互動式 API 文件(由 Swagger UI 提供): +你將看到自動的互動式 API 文件(由 [Swagger UI](https://github.com/swagger-api/swagger-ui) 提供): ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) ### 替代 API 文件 { #alternative-api-docs } -現在,前往 http://127.0.0.1:8000/redoc. +現在,前往 [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)。 -你將看到另一種自動文件(由 ReDoc 提供): +你將看到另一種自動文件(由 [ReDoc](https://github.com/Rebilly/ReDoc) 提供): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -92,7 +92,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) #### API 「schema」 { #api-schema } -在這種情況下,OpenAPI 是一個規範,它規定了如何定義 API 的 schema。 +在這種情況下,[OpenAPI](https://github.com/OAI/OpenAPI-Specification) 是一個規範,它規定了如何定義 API 的 schema。 這個 schema 定義包含了你的 API 路徑、可能接收的參數等內容。 @@ -110,7 +110,7 @@ OpenAPI 為你的 API 定義了 API 的 schema。而該 schema 會包含你的 A 如果你好奇原始的 OpenAPI schema 長什麼樣子,FastAPI 會自動生成一個包含所有 API 描述的 JSON(schema)。 -你可以直接在 http://127.0.0.1:8000/openapi.json 查看它。 +你可以直接在 [http://127.0.0.1:8000/openapi.json](http://127.0.0.1:8000/openapi.json) 查看它。 它會顯示一個 JSON,類似於: @@ -143,9 +143,58 @@ OpenAPI schema 驅動了兩個互動式文件系統。 你也可以用它自動生成程式碼,讓用戶端與你的 API 通訊。例如前端、手機或物聯網(IoT)應用程式。 +### 在 `pyproject.toml` 設定應用的 `entrypoint` { #configure-the-app-entrypoint-in-pyproject-toml } + +你可以在 `pyproject.toml` 中設定你的應用位置,例如: + +```toml +[tool.fastapi] +entrypoint = "main:app" +``` + +這個 `entrypoint` 會告訴 `fastapi` 指令應該用下面的方式匯入 app: + +```python +from main import app +``` + +如果你的程式碼結構像是: + +``` +. +├── backend +│   ├── main.py +│   ├── __init__.py +``` + +那你應該把 `entrypoint` 設為: + +```toml +[tool.fastapi] +entrypoint = "backend.main:app" +``` + +這等同於: + +```python +from backend.main import app +``` + +### 搭配路徑使用 `fastapi dev` { #fastapi-dev-with-path } + +你也可以把檔案路徑傳給 `fastapi dev` 指令,它會自動猜測要使用的 FastAPI app 物件: + +```console +$ fastapi dev main.py +``` + +但這樣每次執行 `fastapi` 指令時都要記得傳入正確路徑。 + +此外,其他工具可能找不到它,例如 [VS Code 擴充套件](../editor-support.md) 或 [FastAPI Cloud](https://fastapicloud.com),因此建議在 `pyproject.toml` 中使用 `entrypoint`。 + ### 部署你的應用程式(可選) { #deploy-your-app-optional } -你可以選擇將你的 FastAPI 應用程式部署到 FastAPI Cloud,如果還沒有,去加入候補名單吧。🚀 +你可以選擇將你的 FastAPI 應用程式部署到 [FastAPI Cloud](https://fastapicloud.com),如果還沒有,去加入候補名單吧。🚀 如果你已經有 **FastAPI Cloud** 帳號(我們已從候補名單邀請你 😉),你可以用一個指令部署你的應用程式。 @@ -191,7 +240,7 @@ Deploying to FastAPI Cloud... `FastAPI` 是一個直接繼承自 `Starlette` 的類別。 -你同樣可以透過 `FastAPI` 來使用 Starlette 所有的功能。 +你同樣可以透過 `FastAPI` 來使用 [Starlette](https://www.starlette.dev/) 所有的功能。 /// @@ -336,7 +385,7 @@ Python 中的 `@something` 語法被稱為「裝飾器」。 /// note -如果你不知道差別,請查看 [Async: *"In a hurry?"*](../async.md#in-a-hurry){.internal-link target=_blank}. +如果你不知道差別,請查看 [Async: *"In a hurry?"*](../async.md#in-a-hurry)。 /// @@ -352,11 +401,11 @@ Python 中的 `@something` 語法被稱為「裝飾器」。 ### 第六步:部署 { #step-6-deploy-it } -用一行指令將你的應用程式部署到 **FastAPI Cloud**:`fastapi deploy`。🎉 +用一行指令將你的應用程式部署到 **[FastAPI Cloud](https://fastapicloud.com)**:`fastapi deploy`。🎉 #### 關於 FastAPI Cloud { #about-fastapi-cloud } -**FastAPI Cloud** 由 **FastAPI** 的作者與團隊打造。 +**[FastAPI Cloud](https://fastapicloud.com)** 由 **FastAPI** 的作者與團隊打造。 它讓你以最小的成本完成 API 的**建置**、**部署**與**存取**流程。 diff --git a/docs/zh-hant/docs/tutorial/handling-errors.md b/docs/zh-hant/docs/tutorial/handling-errors.md index f3a7573cd5..b1ffd3e038 100644 --- a/docs/zh-hant/docs/tutorial/handling-errors.md +++ b/docs/zh-hant/docs/tutorial/handling-errors.md @@ -81,7 +81,7 @@ ## 安裝自訂例外處理器 { #install-custom-exception-handlers } -你可以使用 Starlette 的相同例外工具 來加入自訂例外處理器。 +你可以使用 [Starlette 的相同例外工具](https://www.starlette.dev/exceptions/) 來加入自訂例外處理器。 假設你有一個自訂例外 `UnicornException`,你(或你使用的函式庫)可能會 `raise` 它。 diff --git a/docs/zh-hant/docs/tutorial/index.md b/docs/zh-hant/docs/tutorial/index.md index 5e1961fd7b..e191215113 100644 --- a/docs/zh-hant/docs/tutorial/index.md +++ b/docs/zh-hant/docs/tutorial/index.md @@ -15,7 +15,7 @@
```console -$ fastapi dev main.py +$ fastapi dev FastAPI Starting development server 🚀 @@ -62,7 +62,7 @@ $ fastapi dev @@ -76,7 +76,7 @@ $ pip install "fastapi[standard]" /// note | 注意 -當你使用 `pip install "fastapi[standard]"` 安裝時,會包含一些預設的可選標準依賴項,其中包括 `fastapi-cloud-cli`,它可以讓你部署到 FastAPI Cloud。 +當你使用 `pip install "fastapi[standard]"` 安裝時,會包含一些預設的可選標準依賴項,其中包括 `fastapi-cloud-cli`,它可以讓你部署到 [FastAPI Cloud](https://fastapicloud.com)。 如果你不想包含那些可選的依賴項,你可以改為安裝 `pip install fastapi`。 @@ -84,6 +84,12 @@ $ pip install "fastapi[standard]" /// +/// tip + +FastAPI 提供了 [VS Code 官方擴充功能](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode)(以及 Cursor),包含許多功能,例如路徑操作探索器、路徑操作搜尋、測試中的 CodeLens 導航(從測試跳到定義)、以及 FastAPI Cloud 的部署與日誌,全部可直接在你的編輯器中完成。 + +/// + ## 進階使用者指南 { #advanced-user-guide } 還有一個**進階使用者指南**你可以在讀完這個**教學 - 使用者指南**後再閱讀。 diff --git a/docs/zh-hant/docs/tutorial/metadata.md b/docs/zh-hant/docs/tutorial/metadata.md index 3243efa89c..720b5d87cb 100644 --- a/docs/zh-hant/docs/tutorial/metadata.md +++ b/docs/zh-hant/docs/tutorial/metadata.md @@ -14,7 +14,7 @@ | `version` | `string` | API 的版本號。這是你自己的應用程式版本,不是 OpenAPI 的版本,例如 `2.5.0`。 | | `terms_of_service` | `str` | 指向 API 服務條款的 URL。若提供,必須是 URL。 | | `contact` | `dict` | 對外公開的 API 聯絡資訊。可包含多個欄位。
contact 欄位
參數型別說明
namestr聯絡人/組織的識別名稱。
urlstr指向聯絡資訊的 URL。必須是 URL 格式。
emailstr聯絡人/組織的電子郵件地址。必須是電子郵件格式。
| -| `license_info` | `dict` | 對外公開的 API 授權資訊。可包含多個欄位。
license_info 欄位
參數型別說明
namestr必填(若有設定 license_info)。API 使用的授權名稱。
identifierstrAPI 的 SPDX 授權表示式。identifier 欄位與 url 欄位互斥。自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。
urlstrAPI 所採用授權的 URL。必須是 URL 格式。
| +| `license_info` | `dict` | 對外公開的 API 授權資訊。可包含多個欄位。
license_info 欄位
參數型別說明
namestr必填(若有設定 license_info)。API 使用的授權名稱。
identifierstrAPI 的 [SPDX](https://spdx.org/licenses/) 授權表示式。identifier 欄位與 url 欄位互斥。自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。
urlstrAPI 所採用授權的 URL。必須是 URL 格式。
| 你可以這樣設定它們: @@ -76,7 +76,7 @@ /// info | 資訊 -在[路徑操作設定]中閱讀更多關於標籤的內容:[Path Operation Configuration](path-operation-configuration.md#tags){.internal-link target=_blank}。 +在 [Path Operation Configuration](path-operation-configuration.md#tags) 中閱讀更多關於標籤的內容。 /// diff --git a/docs/zh-hant/docs/tutorial/middleware.md b/docs/zh-hant/docs/tutorial/middleware.md index ac6f5367d0..42a922d354 100644 --- a/docs/zh-hant/docs/tutorial/middleware.md +++ b/docs/zh-hant/docs/tutorial/middleware.md @@ -15,7 +15,7 @@ 如果你有使用帶有 `yield` 的相依性,其釋放階段的程式碼會在中介軟體之後執行。 -若有背景工作(在[背景工作](background-tasks.md){.internal-link target=_blank}一節會介紹,你稍後會看到),它們會在所有中介軟體之後執行。 +若有背景工作(在[背景工作](background-tasks.md)一節會介紹,你稍後會看到),它們會在所有中介軟體之後執行。 /// @@ -35,9 +35,9 @@ /// tip -請記得,自訂的非標準標頭可以使用 `X-` 前綴。 +請記得,自訂的非標準標頭可以[使用 `X-` 前綴](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)。 -但如果你有自訂標頭並希望瀏覽器端的用戶端能看到它們,你需要在 CORS 設定([CORS(Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank})中使用 Starlette 的 CORS 文件所記載的參數 `expose_headers` 將它們加入。 +但如果你有自訂標頭並希望瀏覽器端的用戶端能看到它們,你需要在 CORS 設定([CORS(跨來源資源共用)](cors.md))中使用 [Starlette 的 CORS 文件](https://www.starlette.dev/middleware/#corsmiddleware)所記載的參數 `expose_headers` 將它們加入。 /// @@ -61,7 +61,7 @@ /// tip -這裡我們使用 `time.perf_counter()` 而不是 `time.time()`,因為在這些用例中它可能更精確。🤓 +這裡我們使用 [`time.perf_counter()`](https://docs.python.org/3/library/time.html#time.perf_counter) 而不是 `time.time()`,因為在這些用例中它可能更精確。🤓 /// @@ -90,6 +90,6 @@ app.add_middleware(MiddlewareB) ## 其他中介軟體 { #other-middlewares } -你之後可以在[進階使用者指南:進階中介軟體](../advanced/middleware.md){.internal-link target=_blank}閱讀更多關於其他中介軟體的內容。 +你之後可以在[進階使用者指南:進階中介軟體](../advanced/middleware.md)閱讀更多關於其他中介軟體的內容。 下一節你將會讀到如何使用中介軟體處理 CORS。 diff --git a/docs/zh-hant/docs/tutorial/path-operation-configuration.md b/docs/zh-hant/docs/tutorial/path-operation-configuration.md index 45c101434d..9ca738a98d 100644 --- a/docs/zh-hant/docs/tutorial/path-operation-configuration.md +++ b/docs/zh-hant/docs/tutorial/path-operation-configuration.md @@ -58,7 +58,7 @@ 由於描述常常較長、跨越多行,你可以在函式的 文件字串(docstring) 中宣告「路徑操作」的描述,**FastAPI** 會從那裡讀取。 -你可以在 docstring 中書寫 Markdown,它會被正確解析並顯示(會考慮 docstring 的縮排)。 +你可以在 docstring 中書寫 [Markdown](https://en.wikipedia.org/wiki/Markdown),它會被正確解析並顯示(會考慮 docstring 的縮排)。 {* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *} diff --git a/docs/zh-hant/docs/tutorial/path-params-numeric-validations.md b/docs/zh-hant/docs/tutorial/path-params-numeric-validations.md index a07f825b05..68eb837e94 100644 --- a/docs/zh-hant/docs/tutorial/path-params-numeric-validations.md +++ b/docs/zh-hant/docs/tutorial/path-params-numeric-validations.md @@ -14,7 +14,7 @@ FastAPI 在 0.95.0 版加入並開始推薦使用 `Annotated`。 如果你使用更舊的版本,嘗試使用 `Annotated` 會出錯。 -請確保在使用 `Annotated` 前,先[升級 FastAPI 版本](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}到至少 0.95.1。 +請確保在使用 `Annotated` 前,先[升級 FastAPI 版本](../deployment/versions.md#upgrading-the-fastapi-versions)到至少 0.95.1。 /// @@ -122,7 +122,7 @@ Python 不會對這個 `*` 做任何事,但它會知道後續的所有參數 ## 小結 { #recap } -使用 `Query`、`Path`(以及你尚未看到的其他類別)時,你可以像在[查詢參數與字串驗證](query-params-str-validations.md){.internal-link target=_blank}中一樣,宣告中繼資料與字串驗證。 +使用 `Query`、`Path`(以及你尚未看到的其他類別)時,你可以像在[查詢參數與字串驗證](query-params-str-validations.md)中一樣,宣告中繼資料與字串驗證。 你也可以宣告數值驗證: diff --git a/docs/zh-hant/docs/tutorial/path-params.md b/docs/zh-hant/docs/tutorial/path-params.md index 373f430cde..d46e32bb14 100644 --- a/docs/zh-hant/docs/tutorial/path-params.md +++ b/docs/zh-hant/docs/tutorial/path-params.md @@ -6,7 +6,7 @@ 路徑參數 `item_id` 的值會作為引數 `item_id` 傳入你的函式。 -所以,如果你執行這個範例並前往 http://127.0.0.1:8000/items/foo,你會看到這樣的回應: +所以,如果你執行這個範例並前往 [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/items/foo),你會看到這樣的回應: ```JSON {"item_id":"foo"} @@ -28,7 +28,7 @@ ## 資料 轉換 { #data-conversion } -如果你執行這個範例並在瀏覽器開啟 http://127.0.0.1:8000/items/3,你會看到這樣的回應: +如果你執行這個範例並在瀏覽器開啟 [http://127.0.0.1:8000/items/3](http://127.0.0.1:8000/items/3),你會看到這樣的回應: ```JSON {"item_id":3} @@ -44,7 +44,7 @@ ## 資料驗證 { #data-validation } -但如果你在瀏覽器前往 http://127.0.0.1:8000/items/foo,你會看到漂亮的 HTTP 錯誤: +但如果你在瀏覽器前往 [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/items/foo),你會看到漂亮的 HTTP 錯誤: ```JSON { @@ -64,7 +64,7 @@ 因為路徑參數 `item_id` 的值是 `"foo"`,它不是 `int`。 -同樣的錯誤也會在你提供 `float` 而不是 `int` 時出現,例如:http://127.0.0.1:8000/items/4.2 +同樣的錯誤也會在你提供 `float` 而不是 `int` 時出現,例如:[http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) /// check @@ -78,7 +78,7 @@ ## 文件 { #documentation } -當你在瀏覽器開啟 http://127.0.0.1:8000/docs,你會看到自動產生、可互動的 API 文件,例如: +當你在瀏覽器開啟 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs),你會看到自動產生、可互動的 API 文件,例如: @@ -92,9 +92,9 @@ ## 基於標準的優勢與替代文件 { #standards-based-benefits-alternative-documentation } -而且因為產生的 schema 來自 OpenAPI 標準,有很多相容的工具可用。 +而且因為產生的 schema 來自 [OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md) 標準,有很多相容的工具可用。 -因此,**FastAPI** 本身也提供另一種 API 文件(使用 ReDoc),你可以在 http://127.0.0.1:8000/redoc 存取: +因此,**FastAPI** 本身也提供另一種 API 文件(使用 ReDoc),你可以在 [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) 存取: @@ -102,7 +102,7 @@ ## Pydantic { #pydantic } -所有資料驗證都由 Pydantic 在底層處理,因此你能直接受惠。而且你可以放心使用。 +所有資料驗證都由 [Pydantic](https://docs.pydantic.dev/) 在底層處理,因此你能直接受惠。而且你可以放心使用。 你可以用相同的型別宣告搭配 `str`、`float`、`bool` 與許多更複雜的資料型別。 diff --git a/docs/zh-hant/docs/tutorial/query-params-str-validations.md b/docs/zh-hant/docs/tutorial/query-params-str-validations.md index ea84234c0e..0932c8d90f 100644 --- a/docs/zh-hant/docs/tutorial/query-params-str-validations.md +++ b/docs/zh-hant/docs/tutorial/query-params-str-validations.md @@ -35,13 +35,13 @@ FastAPI 自 0.95.0 版起加入並開始推薦使用 `Annotated`。 如果你的版本較舊,嘗試使用 `Annotated` 會出錯。 -請先至少 [升級 FastAPI 版本](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} 到 0.95.1 再使用 `Annotated`。 +請先至少 [升級 FastAPI 版本](../deployment/versions.md#upgrading-the-fastapi-versions) 到 0.95.1 再使用 `Annotated`。 /// ## 在 `q` 參數的型別中使用 `Annotated` { #use-annotated-in-the-type-for-the-q-parameter } -還記得先前在 [Python 型別介紹](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank} 提到可以用 `Annotated` 為參數加入中繼資料嗎? +還記得先前在 [Python 型別介紹](../python-types.md#type-hints-with-metadata-annotations) 提到可以用 `Annotated` 為參數加入中繼資料嗎? 現在就用在 FastAPI 上吧。🚀 @@ -157,7 +157,7 @@ q: str = Query(default="rick") 若不使用 `Annotated`、改用「(舊式)預設值」寫法,你在沒有 FastAPI 的「其他地方」呼叫該函式時,就得「記得」傳入正確參數,否則值會和預期不同(例如會得到 `QueryInfo` 或類似的東西,而不是 `str`)。你的編輯器不會提示,Python 執行該函式時也不會抱怨,只有在內部操作失敗時才會出錯。 -因為 `Annotated` 可以有多個中繼資料註解,你甚至可以用同一個函式配合其他工具,例如 Typer。🚀 +因為 `Annotated` 可以有多個中繼資料註解,你甚至可以用同一個函式配合其他工具,例如 [Typer](https://typer.tiangolo.com/)。🚀 ## 加入更多驗證 { #add-more-validations } @@ -369,11 +369,11 @@ http://127.0.0.1:8000/items/?item-query=foobaritems 這種情況下,你可以使用「自訂驗證函式」,它會在一般驗證之後套用(例如先確認值是 `str` 之後)。 -你可以在 `Annotated` 中使用 Pydantic 的 `AfterValidator` 來達成。 +你可以在 `Annotated` 中使用 [Pydantic 的 `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) 來達成。 /// tip | 提示 -Pydantic 也有 `BeforeValidator` 等等。🤓 +Pydantic 也有 [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-before-validator) 等等。🤓 /// diff --git a/docs/zh-hant/docs/tutorial/query-params.md b/docs/zh-hant/docs/tutorial/query-params.md index f21bf40506..89c0834565 100644 --- a/docs/zh-hant/docs/tutorial/query-params.md +++ b/docs/zh-hant/docs/tutorial/query-params.md @@ -182,6 +182,6 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy /// tip | 提示 -你也可以像在[路徑參數](path-params.md#predefined-values){.internal-link target=_blank}中一樣使用 `Enum`。 +你也可以像在[路徑參數](path-params.md#predefined-values)中一樣使用 `Enum`。 /// diff --git a/docs/zh-hant/docs/tutorial/request-files.md b/docs/zh-hant/docs/tutorial/request-files.md index c8606a3f23..4e20544ea4 100644 --- a/docs/zh-hant/docs/tutorial/request-files.md +++ b/docs/zh-hant/docs/tutorial/request-files.md @@ -4,9 +4,9 @@ /// info -若要接收上傳的檔案,請先安裝 `python-multipart`。 +若要接收上傳的檔案,請先安裝 [`python-multipart`](https://github.com/Kludex/python-multipart)。 -請先建立並啟用一個[虛擬環境](../virtual-environments.md){.internal-link target=_blank},然後安裝,例如: +請先建立並啟用一個[虛擬環境](../virtual-environments.md),然後安裝,例如: ```console $ pip install python-multipart @@ -63,8 +63,8 @@ $ pip install python-multipart * 檔案在記憶體中保存到某個大小上限,超過上限後會存到磁碟。 * 因此適合處理大型檔案(例如圖片、影片、大型二進位檔等),而不會耗盡記憶體。 * 你可以取得上傳檔案的中繼資料。 -* 它提供一個類檔案的 `async` 介面。 -* 它會提供實際的 Python `SpooledTemporaryFile` 物件,你可以直接傳給需要類檔案物件的其他函式或函式庫。 +* 它提供一個[file-like](https://docs.python.org/3/glossary.html#term-file-like-object) 的 `async` 介面。 +* 它會提供實際的 Python [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) 物件,你可以直接傳給需要類檔案物件的其他函式或函式庫。 ### `UploadFile` { #uploadfile } @@ -72,13 +72,13 @@ $ pip install python-multipart * `filename`:一個 `str`,為上傳的原始檔名(例如 `myimage.jpg`)。 * `content_type`:一個 `str`,為內容類型(MIME type / media type)(例如 `image/jpeg`)。 -* `file`:一個 `SpooledTemporaryFile`類檔案物件)。這是真正的 Python 檔案物件,你可以直接傳給期待「類檔案」物件的其他函式或函式庫。 +* `file`:一個 [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile)(一個[file-like](https://docs.python.org/3/glossary.html#term-file-like-object) 物件)。這是真正的 Python 檔案物件,你可以直接傳給期待「類檔案」物件的其他函式或函式庫。 `UploadFile` 有以下 `async` 方法。它們底層會呼叫對應的檔案方法(使用內部的 `SpooledTemporaryFile`)。 -* `write(data)`:將 `data`(`str` 或 `bytes`)寫入檔案。 -* `read(size)`:讀取檔案的 `size`(`int`)個位元組/字元。 -* `seek(offset)`:移動到檔案中的位元組位置 `offset`(`int`)。 +* `write(data)`:將 `data` (`str` 或 `bytes`) 寫入檔案。 +* `read(size)`:讀取檔案的 `size` (`int`) 個位元組/字元。 +* `seek(offset)`:移動到檔案中的位元組位置 `offset` (`int`)。 * 例如,`await myfile.seek(0)` 會移到檔案開頭。 * 當你已經執行過 `await myfile.read()`,之後需要再次讀取內容時特別有用。 * `close()`:關閉檔案。 @@ -121,7 +121,7 @@ HTML 表單(`
`)送到伺服器的資料通常使用一種「特 但當表單包含檔案時,會使用 `multipart/form-data` 編碼。若你使用 `File`,**FastAPI** 會知道要從請求本文的正確部分取得檔案。 -若想進一步了解這些編碼與表單欄位,請參考 MDN Web Docs 的 POST。 +若想進一步了解這些編碼與表單欄位,請參考 [MDN web docs 的 `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)。 /// diff --git a/docs/zh-hant/docs/tutorial/request-form-models.md b/docs/zh-hant/docs/tutorial/request-form-models.md index 8cf4a7c5e8..f8a0e8c6c5 100644 --- a/docs/zh-hant/docs/tutorial/request-form-models.md +++ b/docs/zh-hant/docs/tutorial/request-form-models.md @@ -4,9 +4,9 @@ /// info | 說明 -要使用表單,首先安裝 `python-multipart`。 +要使用表單,首先安裝 [`python-multipart`](https://github.com/Kludex/python-multipart)。 -請先建立[虛擬環境](../virtual-environments.md){.internal-link target=_blank}、啟用後再安裝,例如: +請先建立[虛擬環境](../virtual-environments.md)、啟用後再安裝,例如: ```console $ pip install python-multipart diff --git a/docs/zh-hant/docs/tutorial/request-forms-and-files.md b/docs/zh-hant/docs/tutorial/request-forms-and-files.md index 6dcc1c260f..c508bf7f7b 100644 --- a/docs/zh-hant/docs/tutorial/request-forms-and-files.md +++ b/docs/zh-hant/docs/tutorial/request-forms-and-files.md @@ -4,9 +4,9 @@ /// info -要接收上傳的檔案與/或表單資料,請先安裝 `python-multipart`。 +要接收上傳的檔案與/或表單資料,請先安裝 [`python-multipart`](https://github.com/Kludex/python-multipart)。 -請先建立並啟用一個 [虛擬環境](../virtual-environments.md){.internal-link target=_blank},然後再安裝,例如: +請先建立並啟用一個 [虛擬環境](../virtual-environments.md),然後再安裝,例如: ```console $ pip install python-multipart diff --git a/docs/zh-hant/docs/tutorial/request-forms.md b/docs/zh-hant/docs/tutorial/request-forms.md index 733a3e2869..d38db96f1a 100644 --- a/docs/zh-hant/docs/tutorial/request-forms.md +++ b/docs/zh-hant/docs/tutorial/request-forms.md @@ -4,9 +4,9 @@ /// info -要使用表單,請先安裝 `python-multipart`。 +要使用表單,請先安裝 [`python-multipart`](https://github.com/Kludex/python-multipart)。 -請先建立並啟用一個[虛擬環境](../virtual-environments.md){.internal-link target=_blank},然後再安裝,例如: +請先建立並啟用一個[虛擬環境](../virtual-environments.md),然後再安裝,例如: ```console $ pip install python-multipart @@ -56,7 +56,7 @@ HTML 表單(`
`)向伺服器傳送資料時,通常會使用一 但當表單包含檔案時,會使用 `multipart/form-data`。你會在下一章閱讀如何處理檔案。 -若想進一步了解這些編碼與表單欄位,請參考 MDNPOST 網頁文件。 +若想進一步了解這些編碼與表單欄位,請參考 [MDN web docs 的 `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)。 /// diff --git a/docs/zh-hant/docs/tutorial/response-model.md b/docs/zh-hant/docs/tutorial/response-model.md index d22402e180..d9ad9d9d15 100644 --- a/docs/zh-hant/docs/tutorial/response-model.md +++ b/docs/zh-hant/docs/tutorial/response-model.md @@ -13,6 +13,7 @@ FastAPI 會使用這個回傳型別來: * 在 OpenAPI 的「路徑操作」中為回應新增 JSON Schema。 * 這會被自動文件使用。 * 也會被自動用戶端程式碼產生工具使用。 +* 使用 Pydantic 將回傳資料**序列化**為 JSON,而 Pydantic 是用 **Rust** 撰寫的,因此會 **更快很多**。 但更重要的是: @@ -73,9 +74,9 @@ FastAPI 會使用這個 `response_model` 來做所有的資料文件、驗證等 /// info | 說明 -要使用 `EmailStr`,請先安裝 `email-validator`。 +要使用 `EmailStr`,請先安裝 [`email-validator`](https://github.com/JoshData/python-email-validator)。 -請先建立一個[虛擬環境](../virtual-environments.md){.internal-link target=_blank}、啟用它,然後安裝,例如: +請先建立一個[虛擬環境](../virtual-environments.md)、啟用它,然後安裝,例如: ```console $ pip install email-validator @@ -181,7 +182,7 @@ FastAPI 在內部會搭配 Pydantic 做一些事情,來確保不會把類別 ### 直接回傳 Response { #return-a-response-directly } -最常見的情況是[直接回傳 Response(在進階文件中稍後會解釋)](../advanced/response-directly.md){.internal-link target=_blank}。 +最常見的情況是[直接回傳 Response(在進階文件中稍後會解釋)](../advanced/response-directly.md)。 {* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} @@ -257,7 +258,7 @@ FastAPI 在內部會搭配 Pydantic 做一些事情,來確保不會把類別 * `response_model_exclude_defaults=True` * `response_model_exclude_none=True` -如 Pydantic 文件中對 `exclude_defaults` 與 `exclude_none` 的說明。 +如 [Pydantic 文件](https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict)中對 `exclude_defaults` 與 `exclude_none` 的說明。 /// diff --git a/docs/zh-hant/docs/tutorial/response-status-code.md b/docs/zh-hant/docs/tutorial/response-status-code.md index cbcc67ca55..9ac2e41dab 100644 --- a/docs/zh-hant/docs/tutorial/response-status-code.md +++ b/docs/zh-hant/docs/tutorial/response-status-code.md @@ -20,7 +20,7 @@ /// info | 資訊 -`status_code` 也可以接收一個 `IntEnum`,例如 Python 的 `http.HTTPStatus`。 +`status_code` 也可以接收一個 `IntEnum`,例如 Python 的 [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus)。 /// @@ -66,7 +66,7 @@ FastAPI 知道這點,並會產生聲明「無回應本文」的 OpenAPI 文件 /// tip | 提示 -想深入瞭解各狀態碼與其用途,請參考 MDN 關於 HTTP 狀態碼的文件。 +想深入瞭解各狀態碼與其用途,請參考 [MDN 關於 HTTP 狀態碼的文件](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)。 /// @@ -98,4 +98,4 @@ FastAPI 知道這點,並會產生聲明「無回應本文」的 OpenAPI 文件 ## 變更預設值 { #changing-the-default } -稍後在 [進階使用者指南](../advanced/response-change-status-code.md){.internal-link target=_blank} 中,你會看到如何回傳一個不同於此處所宣告預設值的狀態碼。 +稍後在 [進階使用者指南](../advanced/response-change-status-code.md) 中,你會看到如何回傳一個不同於此處所宣告預設值的狀態碼。 diff --git a/docs/zh-hant/docs/tutorial/schema-extra-example.md b/docs/zh-hant/docs/tutorial/schema-extra-example.md index 661938ac26..1c2caef85b 100644 --- a/docs/zh-hant/docs/tutorial/schema-extra-example.md +++ b/docs/zh-hant/docs/tutorial/schema-extra-example.md @@ -12,7 +12,7 @@ 這些額外資訊會原封不動加入該模型輸出的 JSON Schema,並且會用在 API 文件裡。 -你可以使用屬性 `model_config`(接收一個 `dict`),詳見 Pydantic 文件:Configuration。 +你可以使用屬性 `model_config`(接收一個 `dict`),詳見 [Pydantic 文件:Configuration](https://docs.pydantic.dev/latest/api/config/)。 你可以將 `"json_schema_extra"` 設為一個 `dict`,其中包含你想在產生的 JSON Schema 中出現的任何額外資料,包括 `examples`。 @@ -145,12 +145,12 @@ OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)新增了對 `examples` 的支援 OpenAPI 也在規範的其他部分新增了 `example` 與 `examples` 欄位: -* `Parameter Object`(規範),對應到 FastAPI 的: +* [`Parameter Object`(規範)](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-object),對應到 FastAPI 的: * `Path()` * `Query()` * `Header()` * `Cookie()` -* `Request Body Object` 中的 `content` 欄位裡的 `Media Type Object`(規範),對應到 FastAPI 的: +* [`Request Body Object` 中的 `content` 欄位裡的 `Media Type Object`(規範)](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#media-type-object),對應到 FastAPI 的: * `Body()` * `File()` * `Form()` @@ -163,7 +163,7 @@ OpenAPI 也在規範的其他部分新增了 `example` 與 `examples` 欄位: ### JSON Schema 的 `examples` 欄位 { #json-schemas-examples-field } -後來 JSON Schema 在新版本規範中新增了 `examples` 欄位。 +後來 JSON Schema 在新版本規範中新增了 [`examples`](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5) 欄位。 接著新的 OpenAPI 3.1.0 以最新版本(JSON Schema 2020-12)為基礎,該版本就包含這個新的 `examples` 欄位。 diff --git a/docs/zh-hant/docs/tutorial/security/first-steps.md b/docs/zh-hant/docs/tutorial/security/first-steps.md index 109f59a37a..7f12ec1a3a 100644 --- a/docs/zh-hant/docs/tutorial/security/first-steps.md +++ b/docs/zh-hant/docs/tutorial/security/first-steps.md @@ -26,11 +26,11 @@ /// info -當你使用 `pip install "fastapi[standard]"` 指令安裝時,`python-multipart` 套件會隨 FastAPI 自動安裝。 +當你使用 `pip install "fastapi[standard]"` 指令安裝時,[`python-multipart`](https://github.com/Kludex/python-multipart) 套件會隨 FastAPI 自動安裝。 不過若只執行 `pip install fastapi`,預設不會包含 `python-multipart`。 -若要手動安裝,請先建立並啟用一個[虛擬環境](../../virtual-environments.md){.internal-link target=_blank},接著執行: +若要手動安裝,請先建立並啟用一個[虛擬環境](../../virtual-environments.md),接著執行: ```console $ pip install python-multipart @@ -45,7 +45,7 @@ $ pip install python-multipart
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -54,7 +54,7 @@ $ fastapi dev main.py ## 檢查 { #check-it } -開啟互動式文件:http://127.0.0.1:8000/docs。 +開啟互動式文件:[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 你會看到類似這樣: @@ -140,7 +140,7 @@ FastAPI 提供多層抽象的工具來實作這些安全機制。 由於使用了相對 URL,若你的 API 位於 `https://example.com/`,那它會指向 `https://example.com/token`;但若你的 API 位於 `https://example.com/api/v1/`,那它會指向 `https://example.com/api/v1/token`。 -使用相對 URL 很重要,能確保你的應用在像是[在 Proxy 後方](../../advanced/behind-a-proxy.md){.internal-link target=_blank}這類進階情境中仍能正常運作。 +使用相對 URL 很重要,能確保你的應用在像是[在 Proxy 後方](../../advanced/behind-a-proxy.md)這類進階情境中仍能正常運作。 /// diff --git a/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md b/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md index d6761a0051..abd920ce6f 100644 --- a/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md +++ b/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md @@ -24,13 +24,13 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4 一週後,權杖會過期,使用者就不再被授權,需要再次登入以取得新的權杖。而如果使用者(或第三方)試圖修改權杖來改變有效期,你也能發現,因為簽名不會相符。 -如果你想玩玩看 JWT 權杖並了解其運作,請參考 https://jwt.io。 +如果你想玩玩看 JWT 權杖並了解其運作,請參考 [https://jwt.io](https://jwt.io/)。 ## 安裝 `PyJWT` { #install-pyjwt } 我們需要安裝 `PyJWT` 才能在 Python 中產生與驗證 JWT 權杖。 -請先建立並啟用一個[虛擬環境](../../virtual-environments.md){.internal-link target=_blank},然後安裝 `pyjwt`: +請先建立並啟用一個[虛擬環境](../../virtual-environments.md),然後安裝 `pyjwt`:
@@ -46,7 +46,7 @@ $ pip install pyjwt 如果你打算使用像 RSA 或 ECDSA 這類的數位簽章演算法,應該安裝帶有加密函式庫相依的 `pyjwt[crypto]`。 -更多內容可參考 PyJWT 安裝文件。 +更多內容可參考 [PyJWT 安裝文件](https://pyjwt.readthedocs.io/en/latest/installation.html)。 /// @@ -72,7 +72,7 @@ pwdlib 是一個很棒的 Python 套件,用來處理密碼雜湊。 建議使用的演算法是「Argon2」。 -請先建立並啟用一個[虛擬環境](../../virtual-environments.md){.internal-link target=_blank},然後以 Argon2 支援安裝 pwdlib: +請先建立並啟用一個[虛擬環境](../../virtual-environments.md),然後以 Argon2 支援安裝 pwdlib:
@@ -200,7 +200,7 @@ JWT 除了用來識別使用者並允許他直接對你的 API 執行操作外 ## 試試看 { #check-it } -啟動伺服器並前往文件頁:http://127.0.0.1:8000/docs。 +啟動伺服器並前往文件頁:[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 你會看到這樣的介面: diff --git a/docs/zh-hant/docs/tutorial/security/simple-oauth2.md b/docs/zh-hant/docs/tutorial/security/simple-oauth2.md index 3b9aae3416..251848aa5a 100644 --- a/docs/zh-hant/docs/tutorial/security/simple-oauth2.md +++ b/docs/zh-hant/docs/tutorial/security/simple-oauth2.md @@ -146,7 +146,7 @@ UserInDB( /// info -想更完整地了解 `**user_dict`,請回到[**額外模型** 的文件](../extra-models.md#about-user-in-dict){.internal-link target=_blank}。 +想更完整地了解 `**user_dict`,請回到[**額外模型** 的文件](../extra-models.md#about-user-in-dict)。 /// @@ -216,7 +216,7 @@ UserInDB( ## 實際操作看看 { #see-it-in-action } -開啟互動式文件:http://127.0.0.1:8000/docs。 +開啟互動式文件:[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 ### 驗證身分 { #authenticate } diff --git a/docs/zh-hant/docs/tutorial/sql-databases.md b/docs/zh-hant/docs/tutorial/sql-databases.md index 930dc4e8a5..a37e164321 100644 --- a/docs/zh-hant/docs/tutorial/sql-databases.md +++ b/docs/zh-hant/docs/tutorial/sql-databases.md @@ -2,9 +2,9 @@ FastAPI 不強制你使用 SQL(關聯式)資料庫。你可以使用任何你想要的資料庫。 -這裡我們會用 SQLModel 作為範例。 +這裡我們會用 [SQLModel](https://sqlmodel.tiangolo.com/) 作為範例。 -SQLModel 建立在 SQLAlchemy 與 Pydantic 之上。它由 FastAPI 的作者開發,非常適合需要使用 SQL 資料庫的 FastAPI 應用。 +SQLModel 建立在 [SQLAlchemy](https://www.sqlalchemy.org/) 與 Pydantic 之上。它由 FastAPI 的作者開發,非常適合需要使用 SQL 資料庫的 FastAPI 應用。 /// tip | 提示 @@ -26,15 +26,15 @@ SQLModel 建立在 https://github.com/fastapi/full-stack-fastapi-template +有一個包含 FastAPI 與 PostgreSQL 的官方專案腳手架,還有前端與更多工具:[https://github.com/fastapi/full-stack-fastapi-template](https://github.com/fastapi/full-stack-fastapi-template) /// -這是一份非常簡短的教學,如果你想更全面學習資料庫、SQL,或更進階的功能,請參考 SQLModel 文件。 +這是一份非常簡短的教學,如果你想更全面學習資料庫、SQL,或更進階的功能,請參考 [SQLModel 文件](https://sqlmodel.tiangolo.com/)。 ## 安裝 `SQLModel` { #install-sqlmodel } -首先,請先建立你的[虛擬環境](../virtual-environments.md){.internal-link target=_blank}、啟用它,然後安裝 `sqlmodel`: +首先,請先建立你的[虛擬環境](../virtual-environments.md)、啟用它,然後安裝 `sqlmodel`:
@@ -65,7 +65,7 @@ $ pip install sqlmodel * `Field(primary_key=True)` 告訴 SQLModel,`id` 是 SQL 資料庫中的「主鍵」。 (你可以在 SQLModel 文件中進一步了解 SQL 主鍵) - 注意:我們在主鍵欄位使用 `int | None`,這樣在 Python 程式碼中我們可以「在沒有 `id` 的情況下建立物件」(`id=None`),假設資料庫在儲存時會「自動產生」。SQLModel 瞭解資料庫會提供 `id`,並且在資料庫綱要中「將該欄位定義為非空的 `INTEGER`」。詳情請見 SQLModel 文件:主鍵。 + 注意:我們在主鍵欄位使用 `int | None`,這樣在 Python 程式碼中我們可以「在沒有 `id` 的情況下建立物件」(`id=None`),假設資料庫在儲存時會「自動產生」。SQLModel 瞭解資料庫會提供 `id`,並且在資料庫綱要中「將該欄位定義為非空的 `INTEGER`」。詳情請見 [SQLModel 文件:主鍵](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id)。 * `Field(index=True)` 告訴 SQLModel 應為此欄位建立「SQL 索引」,以便在用此欄位過濾讀取資料時更快查詢。 @@ -111,7 +111,7 @@ SQLModel 的 `engine`(底層實際上是 SQLAlchemy 的 `engine`)是用來 /// tip | 提示 -SQLModel 之後會提供包裝 Alembic 的遷移工具,但目前你可以直接使用 Alembic。 +SQLModel 之後會提供包裝 Alembic 的遷移工具,但目前你可以直接使用 [Alembic](https://alembic.sqlalchemy.org/en/latest/)。 /// @@ -152,7 +152,7 @@ SQLModel 之後會提供包裝 Alembic 的遷移工具,但目前你可以直
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -337,7 +337,7 @@ $ fastapi dev main.py
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -352,6 +352,6 @@ $ fastapi dev main.py ## 總結 { #recap } -你可以使用 SQLModel 與 SQL 資料庫互動,並用「資料模型」與「資料表模型」讓程式碼更簡潔。 +你可以使用 [SQLModel](https://sqlmodel.tiangolo.com/) 與 SQL 資料庫互動,並用「資料模型」與「資料表模型」讓程式碼更簡潔。 -你可以在 SQLModel 文件學到更多內容,這裡還有一份更長的 使用 SQLModel 與 FastAPI 的教學。🚀 +你可以在 SQLModel 文件學到更多內容,這裡還有一份更長的 [使用 SQLModel 與 FastAPI 的教學](https://sqlmodel.tiangolo.com/tutorial/fastapi/)。🚀 diff --git a/docs/zh-hant/docs/tutorial/static-files.md b/docs/zh-hant/docs/tutorial/static-files.md index 06b6176760..1b9e92a1c9 100644 --- a/docs/zh-hant/docs/tutorial/static-files.md +++ b/docs/zh-hant/docs/tutorial/static-files.md @@ -23,7 +23,7 @@ 這與使用 `APIRouter` 不同,因為被掛載的應用是完全獨立的。主應用的 OpenAPI 與文件不會包含掛載應用的任何內容,等等。 -你可以在[進階使用者指南](../advanced/index.md){.internal-link target=_blank}中閱讀更多相關內容。 +你可以在[進階使用者指南](../advanced/index.md)中閱讀更多相關內容。 ## 細節 { #details } @@ -37,4 +37,4 @@ ## 更多資訊 { #more-info } -如需更多細節與選項,請參考 Starlette 關於靜態檔案的文件。 +如需更多細節與選項,請參考 [Starlette 關於靜態檔案的文件](https://www.starlette.dev/staticfiles/)。 diff --git a/docs/zh-hant/docs/tutorial/testing.md b/docs/zh-hant/docs/tutorial/testing.md index 0d49fd5d7b..f6bef5d962 100644 --- a/docs/zh-hant/docs/tutorial/testing.md +++ b/docs/zh-hant/docs/tutorial/testing.md @@ -1,18 +1,18 @@ # 測試 { #testing } -多虧了 Starlette,測試 **FastAPI** 應用既簡單又好用。 +多虧了 [Starlette](https://www.starlette.dev/testclient/),測試 **FastAPI** 應用既簡單又好用。 -它是基於 HTTPX 打造,而 HTTPX 的設計又參考了 Requests,所以用起來非常熟悉、直覺。 +它是基於 [HTTPX](https://www.python-httpx.org) 打造,而 HTTPX 的設計又參考了 Requests,所以用起來非常熟悉、直覺。 -借助它,你可以直接用 pytest 來測試 **FastAPI**。 +借助它,你可以直接用 [pytest](https://docs.pytest.org/) 來測試 **FastAPI**。 ## 使用 `TestClient` { #using-testclient } /// info -要使用 `TestClient`,請先安裝 `httpx`。 +要使用 `TestClient`,請先安裝 [`httpx`](https://www.python-httpx.org)。 -請先建立並啟用一個[虛擬環境](../virtual-environments.md){.internal-link target=_blank},然後安裝,例如: +請先建立並啟用一個[虛擬環境](../virtual-environments.md),然後安裝,例如: ```console $ pip install httpx @@ -52,7 +52,7 @@ $ pip install httpx /// tip -如果你想在測試中呼叫其他 `async` 函式,而不只是對 FastAPI 應用發送請求(例如非同步的資料庫函式),請參考進階教學中的[非同步測試](../advanced/async-tests.md){.internal-link target=_blank}。 +如果你想在測試中呼叫其他 `async` 函式,而不只是對 FastAPI 應用發送請求(例如非同步的資料庫函式),請參考進階教學中的[非同步測試](../advanced/async-tests.md)。 /// @@ -64,7 +64,7 @@ $ pip install httpx ### **FastAPI** 應用檔案 { #fastapi-app-file } -假設你的檔案結構如[更大型的應用](bigger-applications.md){.internal-link target=_blank}所述: +假設你的檔案結構如[更大型的應用](bigger-applications.md)所述: ``` . @@ -142,13 +142,13 @@ $ pip install httpx * 要傳遞標頭(headers),在 `headers` 參數中放一個 `dict`。 * 對於 Cookie(cookies),在 `cookies` 參數中放一個 `dict`。 -關於如何把資料傳給後端(使用 `httpx` 或 `TestClient`),更多資訊請參考 HTTPX 文件。 +關於如何把資料傳給後端(使用 `httpx` 或 `TestClient`),更多資訊請參考 [HTTPX 文件](https://www.python-httpx.org)。 /// info 請注意,`TestClient` 接收的是可轉為 JSON 的資料,而不是 Pydantic models。 -如果你的測試裡有一個 Pydantic model,並想在測試時把它的資料送給應用,你可以使用[JSON 相容編碼器](encoder.md){.internal-link target=_blank}中介紹的 `jsonable_encoder`。 +如果你的測試裡有一個 Pydantic model,並想在測試時把它的資料送給應用,你可以使用[JSON 相容編碼器](encoder.md)中介紹的 `jsonable_encoder`。 /// @@ -156,7 +156,7 @@ $ pip install httpx 接下來,你只需要安裝 `pytest`。 -請先建立並啟用一個[虛擬環境](../virtual-environments.md){.internal-link target=_blank},然後安裝,例如: +請先建立並啟用一個[虛擬環境](../virtual-environments.md),然後安裝,例如:
diff --git a/docs/zh-hant/docs/virtual-environments.md b/docs/zh-hant/docs/virtual-environments.md index 74b8b9f8c8..908303dcfd 100644 --- a/docs/zh-hant/docs/virtual-environments.md +++ b/docs/zh-hant/docs/virtual-environments.md @@ -22,7 +22,7 @@ 這個頁面將教你如何使用**虛擬環境**以及了解它們的工作原理。 -如果你計畫使用一個**可以為你管理一切的工具**(包括安裝 Python),試試 uv。 +如果你計畫使用一個**可以為你管理一切的工具**(包括安裝 Python),試試 [uv](https://github.com/astral-sh/uv)。 /// @@ -86,7 +86,7 @@ $ python -m venv .venv //// tab | `uv` -如果你安裝了 `uv`,你也可以使用它來建立一個虛擬環境。 +如果你安裝了 [`uv`](https://github.com/astral-sh/uv),你也可以使用它來建立一個虛擬環境。
@@ -150,7 +150,7 @@ $ .venv\Scripts\Activate.ps1 //// tab | Windows Bash -或者,如果你在 Windows 上使用 Bash(例如 Git Bash): +或者,如果你在 Windows 上使用 Bash(例如 [Git Bash](https://gitforwindows.org/)):
@@ -216,7 +216,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python /// tip -如果你使用 `uv` 來安裝內容,而不是 `pip`,那麼你就不需要升級 `pip`。😎 +如果你使用 [`uv`](https://github.com/astral-sh/uv) 來安裝內容,而不是 `pip`,那麼你就不需要升級 `pip`。😎 /// @@ -268,7 +268,7 @@ $ python -m ensurepip --upgrade /// tip -如果你使用 `uv` 來建立虛擬環境,它會自動為你完成這個操作,你可以跳過這一步。😎 +如果你使用 [`uv`](https://github.com/astral-sh/uv) 來建立虛擬環境,它會自動為你完成這個操作,你可以跳過這一步。😎 /// @@ -340,7 +340,7 @@ $ pip install "fastapi[standard]" //// tab | `uv` -如果你有 `uv`: +如果你有 [`uv`](https://github.com/astral-sh/uv):
@@ -372,7 +372,7 @@ $ pip install -r requirements.txt //// tab | `uv` -如果你有 `uv`: +如果你有 [`uv`](https://github.com/astral-sh/uv):
@@ -416,8 +416,8 @@ Hello World 例如: -* VS Code -* PyCharm +* [VS Code](https://code.visualstudio.com/docs/python/environments#_select-and-activate-an-environment) +* [PyCharm](https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html) /// tip @@ -455,7 +455,7 @@ $ deactivate ## 為什麼要使用虛擬環境 { #why-virtual-environments } -你需要安裝 Python 才能使用 FastAPI。 +你需要安裝 [Python](https://www.python.org/) 才能使用 FastAPI。 接下來,你需要**安裝** FastAPI 以及你想使用的其他**套件**。 @@ -564,7 +564,7 @@ $ pip install "fastapi[standard]"
-這會從 PyPI 下載一個壓縮檔案,其中包含 FastAPI 的程式碼。 +這會從 [PyPI](https://pypi.org/project/fastapi/) 下載一個壓縮檔案,其中包含 FastAPI 的程式碼。 它還會**下載** FastAPI 所依賴的其他套件的檔案。 @@ -627,7 +627,7 @@ $ .venv\Scripts\Activate.ps1 //// tab | Windows Bash -或者如果你在 Windows 上使用 Bash(例如 Git Bash): +或者如果你在 Windows 上使用 Bash(例如 [Git Bash](https://gitforwindows.org/)):
@@ -639,13 +639,13 @@ $ source .venv/Scripts/activate //// -這個命令會建立或修改一些[環境變數](environment-variables.md){.internal-link target=_blank},這些環境變數將在接下來的指令中可用。 +這個命令會建立或修改一些[環境變數](environment-variables.md),這些環境變數將在接下來的指令中可用。 其中之一是 `PATH` 變數。 /// tip -你可以在 [環境變數](environment-variables.md#path-environment-variable){.internal-link target=_blank} 部分了解更多關於 `PATH` 環境變數的內容。 +你可以在 [環境變數](environment-variables.md#path-environment-variable) 部分了解更多關於 `PATH` 環境變數的內容。 /// @@ -819,7 +819,7 @@ Traceback (most recent call last):
-但如果你停用虛擬環境並啟用 `prisoner-of-askaban` 的新虛擬環境,那麼當你執行 `python` 時,它會使用 `prisoner-of-askaban` 中虛擬環境的 Python。 +但如果你停用虛擬環境並啟用 `prisoner-of-azkaban` 的新虛擬環境,那麼當你執行 `python` 時,它會使用 `prisoner-of-azkaban` 中虛擬環境的 Python。
@@ -846,7 +846,7 @@ I solemnly swear 🐺 有許多**替代方案**來管理虛擬環境、套件依賴(requirements)、專案。 -當你準備好並想要使用一個工具來**管理整個專案**、套件依賴、虛擬環境等,建議你嘗試 uv。 +當你準備好並想要使用一個工具來**管理整個專案**、套件依賴、虛擬環境等,建議你嘗試 [uv](https://github.com/astral-sh/uv)。 `uv` 可以執行許多操作,它可以: From 453988f359de536d52ac985e3dbd4d7dffc701bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Mar 2026 17:06:04 +0000 Subject: [PATCH 16/69] =?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 772f81eb68..3d868e034e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Translations +* 🌐 Update translations for zh-hant (update-outdated). PR [#15178](https://github.com/fastapi/fastapi/pull/15178) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh-hant (add-missing). PR [#15176](https://github.com/fastapi/fastapi/pull/15176) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (add-missing). PR [#15175](https://github.com/fastapi/fastapi/pull/15175) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ja (update-outdated). PR [#15171](https://github.com/fastapi/fastapi/pull/15171) by [@tiangolo](https://github.com/tiangolo). From 12bbd9453fe1255a0ff17632afdf0dfac8d9a86d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 20 Mar 2026 18:06:37 +0100 Subject: [PATCH 17/69] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20fo?= =?UTF-8?q?r=20zh=20(update-outdated)=20(#15177)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov --- docs/zh/docs/_llm-test.md | 266 +----------------- docs/zh/docs/advanced/additional-responses.md | 4 +- .../docs/advanced/additional-status-codes.md | 6 +- .../zh/docs/advanced/advanced-dependencies.md | 4 +- docs/zh/docs/advanced/async-tests.md | 8 +- docs/zh/docs/advanced/behind-a-proxy.md | 26 +- docs/zh/docs/advanced/custom-response.md | 116 +++----- docs/zh/docs/advanced/dataclasses.md | 8 +- docs/zh/docs/advanced/events.md | 6 +- docs/zh/docs/advanced/generate-clients.md | 16 +- docs/zh/docs/advanced/index.md | 6 +- docs/zh/docs/advanced/middleware.md | 12 +- docs/zh/docs/advanced/openapi-callbacks.md | 14 +- docs/zh/docs/advanced/openapi-webhooks.md | 4 +- .../path-operation-advanced-configuration.md | 6 +- .../advanced/response-change-status-code.md | 2 +- docs/zh/docs/advanced/response-cookies.md | 4 +- docs/zh/docs/advanced/response-directly.md | 29 +- docs/zh/docs/advanced/response-headers.md | 6 +- .../docs/advanced/security/http-basic-auth.md | 2 +- docs/zh/docs/advanced/security/index.md | 4 +- .../docs/advanced/security/oauth2-scopes.md | 4 +- docs/zh/docs/advanced/settings.md | 16 +- docs/zh/docs/advanced/sub-applications.md | 10 +- docs/zh/docs/advanced/templates.md | 8 +- docs/zh/docs/advanced/testing-websockets.md | 2 +- .../docs/advanced/using-request-directly.md | 4 +- docs/zh/docs/advanced/websockets.md | 26 +- docs/zh/docs/advanced/wsgi.md | 6 +- docs/zh/docs/alternatives.md | 62 ++-- docs/zh/docs/async.md | 24 +- docs/zh/docs/benchmarks.md | 2 +- docs/zh/docs/deployment/cloud.md | 8 +- docs/zh/docs/deployment/concepts.md | 10 +- docs/zh/docs/deployment/docker.md | 46 +-- docs/zh/docs/deployment/fastapicloud.md | 4 +- docs/zh/docs/deployment/https.md | 16 +- docs/zh/docs/deployment/index.md | 2 +- docs/zh/docs/deployment/manually.md | 12 +- docs/zh/docs/deployment/server-workers.md | 6 +- docs/zh/docs/deployment/versions.md | 6 +- docs/zh/docs/environment-variables.md | 10 +- docs/zh/docs/fastapi-cli.md | 71 ++++- docs/zh/docs/features.md | 26 +- docs/zh/docs/help-fastapi.md | 58 ++-- docs/zh/docs/history-design-future.md | 12 +- .../authentication-error-status-code.md | 2 +- docs/zh/docs/how-to/conditional-openapi.md | 2 +- docs/zh/docs/how-to/configure-swagger-ui.md | 6 +- docs/zh/docs/how-to/custom-docs-ui-assets.md | 12 +- .../docs/how-to/custom-request-and-route.md | 8 +- docs/zh/docs/how-to/extending-openapi.md | 4 +- docs/zh/docs/how-to/general.md | 22 +- docs/zh/docs/how-to/graphql.md | 30 +- docs/zh/docs/how-to/index.md | 2 +- ...migrate-from-pydantic-v1-to-pydantic-v2.md | 6 +- docs/zh/docs/how-to/testing-database.md | 6 +- docs/zh/docs/index.md | 118 ++++---- docs/zh/docs/project-generation.md | 2 +- docs/zh/docs/python-types.md | 10 +- docs/zh/docs/tutorial/background-tasks.md | 6 +- docs/zh/docs/tutorial/bigger-applications.md | 49 +++- docs/zh/docs/tutorial/body-nested-models.md | 2 +- docs/zh/docs/tutorial/body-updates.md | 6 +- docs/zh/docs/tutorial/body.md | 12 +- docs/zh/docs/tutorial/cors.md | 8 +- docs/zh/docs/tutorial/debugging.md | 2 +- ...pendencies-in-path-operation-decorators.md | 4 +- .../dependencies/dependencies-with-yield.md | 18 +- .../dependencies/global-dependencies.md | 6 +- docs/zh/docs/tutorial/dependencies/index.md | 4 +- docs/zh/docs/tutorial/encoder.md | 4 +- docs/zh/docs/tutorial/extra-data-types.md | 4 +- docs/zh/docs/tutorial/extra-models.md | 10 +- docs/zh/docs/tutorial/first-steps.md | 77 ++++- docs/zh/docs/tutorial/handling-errors.md | 2 +- docs/zh/docs/tutorial/index.md | 14 +- docs/zh/docs/tutorial/metadata.md | 4 +- docs/zh/docs/tutorial/middleware.md | 10 +- .../tutorial/path-operation-configuration.md | 2 +- .../path-params-numeric-validations.md | 6 +- docs/zh/docs/tutorial/path-params.md | 16 +- .../tutorial/query-params-str-validations.md | 20 +- docs/zh/docs/tutorial/query-params.md | 14 +- docs/zh/docs/tutorial/request-files.md | 24 +- docs/zh/docs/tutorial/request-form-models.md | 4 +- .../docs/tutorial/request-forms-and-files.md | 4 +- docs/zh/docs/tutorial/request-forms.md | 8 +- docs/zh/docs/tutorial/response-model.md | 9 +- docs/zh/docs/tutorial/response-status-code.md | 6 +- docs/zh/docs/tutorial/schema-extra-example.md | 8 +- docs/zh/docs/tutorial/security/first-steps.md | 10 +- docs/zh/docs/tutorial/security/oauth2-jwt.md | 10 +- .../docs/tutorial/security/simple-oauth2.md | 4 +- docs/zh/docs/tutorial/sql-databases.md | 22 +- docs/zh/docs/tutorial/static-files.md | 4 +- docs/zh/docs/tutorial/testing.md | 24 +- docs/zh/docs/virtual-environments.md | 30 +- 98 files changed, 777 insertions(+), 920 deletions(-) diff --git a/docs/zh/docs/_llm-test.md b/docs/zh/docs/_llm-test.md index 05c512e99b..2e9e7816e0 100644 --- a/docs/zh/docs/_llm-test.md +++ b/docs/zh/docs/_llm-test.md @@ -11,7 +11,7 @@ * 检查翻译是否正确。 * 如有需要,改进你的语言特定提示、通用提示,或英文文档。 * 然后手动修正翻译中剩余的问题,确保这是一个优秀的译文。 -* 重新翻译,在已有的优秀译文基础上进行。理想情况是 LLM 不再对译文做任何更改。这意味着通用提示和你的语言特定提示已经尽可能完善(有时它仍会做一些看似随机的改动,原因是LLM 不是确定性算法)。 +* 重新翻译,在已有的优秀译文基础上进行。理想情况是 LLM 不再对译文做任何更改。这意味着通用提示和你的语言特定提示已经尽可能完善(有时它仍会做一些看似随机的改动,原因是[LLM 不是确定性算法](https://doublespeak.chat/#/handbook#deterministic-output))。 测试如下: @@ -169,15 +169,15 @@ Some text 链接文本应被翻译,链接地址应保持不变: * [链接到上面的标题](#code-snippets) -* [内部链接](index.md#installation){.internal-link target=_blank} -* 外部链接 -* 样式链接 -* 脚本链接 -* 图片链接 +* [内部链接](index.md#installation) +* [外部链接](https://sqlmodel.tiangolo.com/) +* [样式链接](https://fastapi.tiangolo.com/css/styles.css) +* [脚本链接](https://fastapi.tiangolo.com/js/logic.js) +* [图片链接](https://fastapi.tiangolo.com/img/foo.jpg) 链接文本应被翻译,且链接地址应指向对应的译文页面: -* FastAPI 链接 +* [FastAPI 链接](https://fastapi.tiangolo.com/zh/) //// @@ -501,255 +501,3 @@ Hello again. 参见例如 `docs/de/llm-prompt.md` 中的 `### List of English terms and their preferred German translations` 部分。 //// - -//// - -翻译(术语)对照: - -//// tab | 测试(译文) - -* 你 -* 你的 - -* 例如 -* 等等 - -* 将 `foo` 作为 `int` -* 将 `bar` 作为 `str` -* 将 `baz` 作为 `list` - -* 教程 - 用户指南 -* 高级用户指南 -* SQLModel 文档 -* API 文档 -* 自动文档 - -* 数据科学 -* 深度学习 -* 机器学习 -* 依赖注入 -* HTTP 基本认证 -* HTTP 摘要认证 -* ISO 格式 -* JSON Schema 标准 -* JSON 模式 -* 模式定义 -* 密码流 -* 移动端 - -* 已弃用 -* 设计的 -* 无效 -* 即时 -* 标准的 -* 默认的 -* 区分大小写 -* 不区分大小写 - -* 为应用提供服务 -* 为页面提供服务 - -* 应用 -* 应用程序 - -* 请求 -* 响应 -* 错误响应 - -* 路径操作 -* 路径操作装饰器 -* 路径操作函数 - -* 主体 -* 请求体 -* 响应体 -* JSON 体 -* 表单体 -* 文件体 -* 函数体 - -* 参数 -* 请求体参数 -* 路径参数 -* 查询参数 -* Cookie 参数 -* Header 参数 -* 表单参数 -* 函数参数 - -* 事件 -* 启动事件 -* 服务器的启动 -* 关闭事件 -* 生命周期事件 - -* 处理器 -* 事件处理器 -* 异常处理器 -* 处理 - -* 模型 -* Pydantic 模型 -* 数据模型 -* 数据库模型 -* 表单模型 -* 模型对象 - -* 类 -* 基类 -* 父类 -* 子类 -* 子类 -* 兄弟类 -* 类方法 - -* 请求头 -* 请求头 -* 授权头 -* `Authorization` 头 -* 转发头 - -* 依赖注入系统 -* 依赖 -* 可依赖对象 -* 依赖项 - -* I/O 受限 -* CPU 受限 -* 并发 -* 并行 -* 多进程 - -* 环境变量 -* 环境变量 -* `PATH` -* `PATH` 变量 - -* 认证 -* 认证提供方 -* 授权 -* 授权表单 -* 授权提供方 -* 用户进行认证 -* 系统对用户进行认证 - -* CLI -* 命令行界面 - -* 服务器 -* 客户端 - -* 云服务提供商 -* 云服务 - -* 开发 -* 开发阶段 - -* dict -* 字典 -* 枚举 -* 枚举 -* 枚举成员 - -* 编码器 -* 解码器 -* 编码 -* 解码 - -* 异常 -* 抛出 - -* 表达式 -* 语句 - -* 前端 -* 后端 - -* GitHub 讨论 -* GitHub Issue - -* 性能 -* 性能优化 - -* 返回类型 -* 返回值 - -* 安全 -* 安全方案 - -* 任务 -* 后台任务 -* 任务函数 - -* 模板 -* 模板引擎 - -* 类型注解 -* 类型提示 - -* 服务器 worker -* Uvicorn worker -* Gunicorn worker -* worker 进程 -* worker 类 -* 工作负载 - -* 部署 -* 部署 - -* SDK -* 软件开发工具包 - -* `APIRouter` -* `requirements.txt` -* Bearer Token -* 破坏性变更 -* Bug -* 按钮 -* 可调用对象 -* 代码 -* 提交 -* 上下文管理器 -* 协程 -* 数据库会话 -* 磁盘 -* 域名 -* 引擎 -* 假 X -* HTTP GET 方法 -* 项 -* 库 -* 生命周期 -* 锁 -* 中间件 -* 移动应用 -* 模块 -* 挂载 -* 网络 -* 源 -* 覆盖 -* 负载 -* 处理器 -* 属性 -* 代理 -* Pull Request -* 查询 -* RAM -* 远程机器 -* 状态码 -* 字符串 -* 标签 -* Web 框架 -* 通配符 -* 返回 -* 校验 - -//// - -//// tab | 信息(译文) - -此清单是不完整且非规范性的,列出(主要是)文档中出现的技术术语。它有助于提示词设计者确定哪些术语需要额外的指引。例如当 LLM 总是把更好的译法改回次优译法,或在你的语言中难以正确变形时。 - -也可参见 `docs/de/llm-prompt.md` 中的 `### List of English terms and their preferred German translations` 部分。 - -//// diff --git a/docs/zh/docs/advanced/additional-responses.md b/docs/zh/docs/advanced/additional-responses.md index aa3d22d1c7..365ba3db4f 100644 --- a/docs/zh/docs/advanced/additional-responses.md +++ b/docs/zh/docs/advanced/additional-responses.md @@ -243,5 +243,5 @@ new_dict = {**old_dict, "new key": "new value"} 要查看响应中究竟可以包含什么,你可以查看 OpenAPI 规范中的以下部分: -* OpenAPI Responses 对象,它包含 `Response Object`。 -* OpenAPI Response 对象,你可以把这里的任何内容直接包含到 `responses` 参数中的每个响应里。包括 `description`、`headers`、`content`(在这里声明不同的媒体类型和 JSON Schemas),以及 `links`。 +* [OpenAPI Responses 对象](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object),它包含 `Response Object`。 +* [OpenAPI Response 对象](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object),你可以把这里的任何内容直接包含到 `responses` 参数中的每个响应里。包括 `description`、`headers`、`content`(在这里声明不同的媒体类型和 JSON Schemas),以及 `links`。 diff --git a/docs/zh/docs/advanced/additional-status-codes.md b/docs/zh/docs/advanced/additional-status-codes.md index 7eeffaf532..af212ad8b1 100644 --- a/docs/zh/docs/advanced/additional-status-codes.md +++ b/docs/zh/docs/advanced/additional-status-codes.md @@ -16,7 +16,7 @@ {* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} -/// warning | 警告 +/// warning 当你直接返回一个像上面例子中的 `Response` 对象时,它会直接返回。 @@ -26,7 +26,7 @@ /// -/// note | 注意 +/// note | 技术细节 你也可以使用 `from starlette.responses import JSONResponse`。  @@ -38,4 +38,4 @@ 如果你直接返回额外的状态码和响应,它们不会包含在 OpenAPI 方案(API 文档)中,因为 FastAPI 没办法预先知道你要返回什么。 -但是你可以使用 [额外的响应](additional-responses.md){.internal-link target=_blank} 在代码中记录这些内容。 +但是你可以使用 [额外的响应](additional-responses.md) 在代码中记录这些内容。 diff --git a/docs/zh/docs/advanced/advanced-dependencies.md b/docs/zh/docs/advanced/advanced-dependencies.md index a547e88814..edaf964c93 100644 --- a/docs/zh/docs/advanced/advanced-dependencies.md +++ b/docs/zh/docs/advanced/advanced-dependencies.md @@ -132,7 +132,7 @@ checker(q="somequery") 这样会话会释放数据库连接,让其他请求可以使用。 -如果你还有其他需要在 `yield` 依赖项中提前退出的用例,请创建一个 GitHub 讨论问题,说明你的具体用例以及为何提前关闭会对你有帮助。 +如果你还有其他需要在 `yield` 依赖项中提前退出的用例,请创建一个 [GitHub 讨论问题](https://github.com/fastapi/fastapi/discussions/new?category=questions),说明你的具体用例以及为何提前关闭会对你有帮助。 如果确有有力的用例需要提前关闭,我会考虑新增一种选择性启用提前关闭的方式。 @@ -144,7 +144,7 @@ checker(q="somequery") ### 后台任务与带 `yield` 的依赖项(技术细节) { #background-tasks-and-dependencies-with-yield-technical-details } -在 FastAPI 0.106.0 之前,`yield` 之后抛出异常是不可行的,因为带 `yield` 的依赖项中的退出代码会在响应发送之后才执行,此时[异常处理器](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}已经运行完毕。 +在 FastAPI 0.106.0 之前,`yield` 之后抛出异常是不可行的,因为带 `yield` 的依赖项中的退出代码会在响应发送之后才执行,此时[异常处理器](../tutorial/handling-errors.md#install-custom-exception-handlers)已经运行完毕。 之所以这样设计,主要是为了允许在后台任务中继续使用依赖项通过 `yield`“产出”的对象,因为退出代码会在后台任务完成之后才执行。 diff --git a/docs/zh/docs/advanced/async-tests.md b/docs/zh/docs/advanced/async-tests.md index 16b8a8c813..2030bb11e2 100644 --- a/docs/zh/docs/advanced/async-tests.md +++ b/docs/zh/docs/advanced/async-tests.md @@ -16,11 +16,11 @@ `TestClient` 在内部通过一些“魔法”操作,使得您可以在普通的 `def` 测试函数中调用异步的 FastAPI 应用程序,并使用标准的 pytest。但当我们在异步函数中使用它时,这种“魔法”就不再生效了。由于测试以异步方式运行,我们无法在测试函数中继续使用 `TestClient`。 -`TestClient` 是基于 HTTPX 的。幸运的是,我们可以直接使用它来测试API。 +`TestClient` 是基于 [HTTPX](https://www.python-httpx.org) 的。幸运的是,我们可以直接使用它来测试 API。 ## 示例 { #example } -举个简单的例子,让我们来看一个[更大的应用](../tutorial/bigger-applications.md){.internal-link target=_blank}和[测试](../tutorial/testing.md){.internal-link target=_blank}中描述的类似文件结构: +举个简单的例子,让我们来看一个与[更大的应用](../tutorial/bigger-applications.md)和[测试](../tutorial/testing.md)中描述的类似文件结构: ``` . @@ -84,7 +84,7 @@ response = client.get('/') /// warning | 警告 -如果您的应用程序依赖于生命周期事件, `AsyncClient` 将不会触发这些事件。为了确保它们被触发,请使用 florimondmanca/asgi-lifespan 中的 `LifespanManager` 。 +如果您的应用程序依赖于生命周期事件, `AsyncClient` 将不会触发这些事件。为了确保它们被触发,请使用 [florimondmanca/asgi-lifespan](https://github.com/florimondmanca/asgi-lifespan#usage) 中的 `LifespanManager` 。 /// @@ -94,6 +94,6 @@ response = client.get('/') /// tip | 提示 -如果您在测试程序中集成异步函数调用的时候遇到一个 `RuntimeError: Task attached to a different loop` 的报错(例如,使用 MongoDB 的 MotorClient 时),请记住,只能在异步函数中实例化需要事件循环的对象,例如在 `@app.on_event("startup")` 回调中初始化。 +如果您在测试程序中集成异步函数调用的时候遇到一个 `RuntimeError: Task attached to a different loop` 的报错(例如,使用 [MongoDB 的 MotorClient](https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop) 时),请记住,只能在异步函数中实例化需要事件循环的对象,例如在 `@app.on_event("startup")` 回调中初始化。 /// diff --git a/docs/zh/docs/advanced/behind-a-proxy.md b/docs/zh/docs/advanced/behind-a-proxy.md index 3ccc65f292..b3c91eb06a 100644 --- a/docs/zh/docs/advanced/behind-a-proxy.md +++ b/docs/zh/docs/advanced/behind-a-proxy.md @@ -16,9 +16,9 @@ 这些代理相关的请求头包括: -- X-Forwarded-For -- X-Forwarded-Proto -- X-Forwarded-Host +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) /// @@ -60,7 +60,7 @@ https://mysuperapp.com/items/ /// tip | 提示 -如果你想了解更多关于 HTTPS 的内容,查看指南:[关于 HTTPS](../deployment/https.md){.internal-link target=_blank}。 +如果你想了解更多关于 HTTPS 的内容,查看指南:[关于 HTTPS](../deployment/https.md)。 /// @@ -228,7 +228,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 请注意,服务器(Uvicorn)不会用这个 `root_path` 做别的事情,只会把它传给应用。 -但是,如果你用浏览器打开 http://127.0.0.1:8000/app,你会看到正常的响应: +但是,如果你用浏览器打开 [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app),你会看到正常的响应: ```JSON { @@ -251,9 +251,9 @@ Uvicorn 会期望代理以 `http://127.0.0.1:8000/app` 访问 Uvicorn,而在 ## 使用 Traefik 进行本地测试 { #testing-locally-with-traefik } -你可以很容易地使用 Traefik 在本地运行一个移除路径前缀的实验。 +你可以很容易地使用 [Traefik](https://docs.traefik.io/) 在本地运行一个移除路径前缀的实验。 -下载 Traefik,它是一个单独的二进制文件,你可以解压压缩包并直接在终端中运行。 +[下载 Traefik](https://github.com/containous/traefik/releases),它是一个单独的二进制文件,你可以解压压缩包并直接在终端中运行。 然后创建一个 `traefik.toml` 文件,内容如下: @@ -330,7 +330,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 ### 查看响应 { #check-the-responses } -现在,如果你访问 Uvicorn 端口对应的 URL:http://127.0.0.1:8000/app,你会看到正常响应: +现在,如果你访问 Uvicorn 端口对应的 URL:[http://127.0.0.1:8000/app](http://127.0.0.1:8000/app),你会看到正常响应: ```JSON { @@ -345,7 +345,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 /// -现在打开包含路径前缀、使用 Traefik 端口的 URL:http://127.0.0.1:9999/api/v1/app。 +现在打开包含路径前缀、使用 Traefik 端口的 URL:[http://127.0.0.1:9999/api/v1/app](http://127.0.0.1:9999/api/v1/app)。 我们得到相同的响应: @@ -370,13 +370,13 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 访问应用的“官方”方式应该是通过我们定义的带有路径前缀的代理。因此,正如预期的那样,如果你尝试不带路径前缀、直接由 Uvicorn 提供的文档界面,它将无法工作,因为它期望通过代理访问。 -你可以在 http://127.0.0.1:8000/docs 查看: +你可以在 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) 查看: 但如果我们在“官方”URL(代理端口为 `9999`)的 `/api/v1/docs` 访问文档界面,它就能正常工作!🎉 -你可以在 http://127.0.0.1:9999/api/v1/docs 查看: +你可以在 [http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs) 查看: @@ -433,7 +433,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 /// -在 http://127.0.0.1:9999/api/v1/docs 的文档界面中,它看起来是这样的: +在文档界面 [http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs) 中,它看起来是这样的: @@ -461,6 +461,6 @@ OpenAPI 规范中的 `servers` 属性是可选的。 ## 挂载子应用 { #mounting-a-sub-application } -如果你需要在使用带有 `root_path` 的代理时挂载一个子应用(参见 [子应用 - 挂载](sub-applications.md){.internal-link target=_blank}),你可以像预期的那样正常操作。 +如果你需要在使用带有 `root_path` 的代理时挂载一个子应用(参见 [子应用 - 挂载](sub-applications.md)),你可以像预期的那样正常操作。 FastAPI 会在内部智能地使用 `root_path`,因此它可以直接正常工作。✨ diff --git a/docs/zh/docs/advanced/custom-response.md b/docs/zh/docs/advanced/custom-response.md index 7c19b73fbc..ce595572dd 100644 --- a/docs/zh/docs/advanced/custom-response.md +++ b/docs/zh/docs/advanced/custom-response.md @@ -1,52 +1,36 @@ # 自定义响应 - HTML、流、文件等 { #custom-response-html-stream-file-others } -**FastAPI** 默认会使用 `JSONResponse` 返回响应。 +默认情况下,**FastAPI** 会返回 JSON 响应。 -你可以通过直接返回 `Response` 来重载它,参见 [直接返回响应](response-directly.md){.internal-link target=_blank}。 +你可以像在 [直接返回响应](response-directly.md) 中那样,直接返回 `Response` 来重载它。 -但如果你直接返回一个 `Response`(或其任意子类,比如 `JSONResponse`),返回数据不会自动转换(即使你声明了 `response_model`),也不会自动生成文档(例如,在生成的 OpenAPI 中,HTTP 头 `Content-Type` 里的特定「媒体类型」不会被包含)。 +但如果你直接返回一个 `Response`(或其任意子类,比如 `JSONResponse`),返回的数据不会自动转换(即使你声明了 `response_model`),也不会自动生成文档(例如,在生成的 OpenAPI 中,HTTP 头 `Content-Type` 里的特定「媒体类型」不会被包含)。 你还可以在 *路径操作装饰器* 中通过 `response_class` 参数声明要使用的 `Response`(例如任意 `Response` 子类)。 你从 *路径操作函数* 中返回的内容将被放在该 `Response` 中。 -并且如果该 `Response` 有一个 JSON 媒体类型(`application/json`),比如使用 `JSONResponse` 或 `UJSONResponse` 的时候,返回的数据将使用你在路径操作装饰器中声明的任何 Pydantic 的 `response_model` 自动转换(和过滤)。 - /// note | 注意 -如果你使用不带有任何媒体类型的响应类,FastAPI 会认为你的响应没有任何内容,所以不会在生成的 OpenAPI 文档中记录响应格式。 +如果你使用不带有媒体类型的响应类,FastAPI 会认为你的响应没有任何内容,所以不会在生成的 OpenAPI 文档中记录响应格式。 /// -## 使用 `ORJSONResponse` { #use-orjsonresponse } - -例如,如果你需要压榨性能,你可以安装并使用 `orjson` 并将响应设置为 `ORJSONResponse`。 - -导入你想要使用的 `Response` 类(子类)然后在 *路径操作装饰器* 中声明它。 - -对于较大的响应,直接返回一个 `Response` 会比返回一个字典快得多。 - -这是因为默认情况下,FastAPI 会检查其中的每一项并确保它可以被序列化为 JSON,使用教程中解释的相同 [JSON 兼容编码器](../tutorial/encoder.md){.internal-link target=_blank}。这正是它允许你返回「任意对象」的原因,例如数据库模型。 - -但如果你确定你返回的内容是「可以用 JSON 序列化」的,你可以将它直接传给响应类,从而避免在传给响应类之前先通过 `jsonable_encoder` 带来的额外开销。 +## JSON 响应 { #json-responses } -{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *} +默认情况下 FastAPI 返回 JSON 响应。 -/// info | 信息 - -参数 `response_class` 也会用来定义响应的「媒体类型」。 +如果你声明了一个[响应模型](../tutorial/response-model.md),FastAPI 会使用 Pydantic 将数据序列化为 JSON。 -在这个例子中,HTTP 头的 `Content-Type` 会被设置成 `application/json`。 +如果你没有声明响应模型,FastAPI 会使用 [JSON 兼容编码器](../tutorial/encoder.md) 中解释的 `jsonable_encoder`,并把结果放进一个 `JSONResponse`。 -并且在 OpenAPI 文档中也会这样记录。 +如果你在 `response_class` 中声明了一个 JSON 媒体类型(`application/json`)的类(比如 `JSONResponse`),你返回的数据会使用你在 *路径操作装饰器* 中声明的任意 Pydantic `response_model` 自动转换(和过滤)。但数据不会由 Pydantic 序列化为 JSON 字节;而是先用 `jsonable_encoder` 转换后传给 `JSONResponse`,由它使用 Python 标准 JSON 库序列化为字节。 -/// +### JSON 性能 { #json-performance } -/// tip | 提示 +简而言之,如果你想要获得最大性能,请使用[响应模型](../tutorial/response-model.md),并且不要在 *路径操作装饰器* 中声明 `response_class`。 -`ORJSONResponse` 目前只在 FastAPI 中可用,而在 Starlette 中不可用。 - -/// +{* ../../docs_src/response_model/tutorial001_01_py310.py ln[15:17] hl[16] *} ## HTML 响应 { #html-response } @@ -69,7 +53,7 @@ ### 返回一个 `Response` { #return-a-response } -正如你在 [直接返回响应](response-directly.md){.internal-link target=_blank} 中了解到的,你也可以通过直接返回响应在 *路径操作* 中直接重载响应。 +正如你在 [直接返回响应](response-directly.md) 中了解到的,你也可以通过直接返回响应在 *路径操作* 中直接重载响应。 和上面一样的例子,返回一个 `HTMLResponse` 看起来可能是这样: @@ -154,37 +138,11 @@ FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它 如上文所述,这是 **FastAPI** 中使用的默认响应。 -### `ORJSONResponse` { #orjsonresponse } - -如上文所述,`ORJSONResponse` 是一个使用 `orjson` 的快速的可选 JSON 响应。 - -/// info | 信息 - -这需要先安装 `orjson`,例如使用 `pip install orjson`。 - -/// - -### `UJSONResponse` { #ujsonresponse } - -`UJSONResponse` 是一个使用 `ujson` 的可选 JSON 响应。 - -/// info | 信息 - -这需要先安装 `ujson`,例如使用 `pip install ujson`。 - -/// - -/// warning | 警告 - -在处理某些边缘情况时,`ujson` 不如 Python 的内置实现那么谨慎。 - -/// - -{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *} +/// note | 技术细节 -/// tip | 提示 +但如果你声明了响应模型或返回类型,将直接使用它来把数据序列化为 JSON,并直接返回一个具备正确 JSON 媒体类型的响应,而不会使用 `JSONResponse` 类。 -`ORJSONResponse` 可能是一个更快的选择。 +这是获得最佳性能的理想方式。 /// @@ -214,31 +172,25 @@ FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它 ### `StreamingResponse` { #streamingresponse } -采用异步生成器或普通生成器/迭代器,然后流式传输响应主体。 - -{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *} - -#### 对类似文件的对象使用 `StreamingResponse` { #using-streamingresponse-with-file-like-objects } +采用异步生成器或普通生成器/迭代器(带有 `yield` 的函数),然后流式传输响应主体。 -如果您有一个类文件对象(例如由 `open()` 返回的对象),你可以创建一个生成器函数来迭代该类文件对象。 +{* ../../docs_src/custom_response/tutorial007_py310.py hl[3,16] *} -这样,你就不必先把它全部读入内存,可以将该生成器函数传给 `StreamingResponse` 并返回它。 - -这也包括许多与云存储、视频处理等交互的库。 +/// note | 技术细节 -{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *} +一个 `async` 任务只有在到达 `await` 时才能被取消。如果没有 `await`,生成器(带有 `yield` 的函数)无法被正确取消,即使已请求取消也可能继续运行。 -1. 这是生成器函数。之所以是「生成器函数」,是因为它内部包含 `yield` 语句。 -2. 通过使用 `with` 代码块,我们可以确保在生成器函数完成后关闭类文件对象。因此,在它完成发送响应之后会被关闭。 -3. 这个 `yield from` 告诉函数去迭代名为 `file_like` 的那个对象。然后,对于每个被迭代出来的部分,都把该部分作为来自这个生成器函数(`iterfile`)的值再 `yield` 出去。 +由于这个小示例不需要任何 `await` 语句,我们添加 `await anyio.sleep(0)`,给事件循环一个处理取消的机会。 - 因此,它是一个把「生成」工作内部转交给其他东西的生成器函数。 +对于大型或无限流,这一点更为重要。 - 通过这种方式,我们可以把它放在 `with` 代码块中,从而确保类文件对象在结束后被关闭。 +/// /// tip | 提示 -注意在这里,因为我们使用的是不支持 `async` 和 `await` 的标准 `open()`,我们使用普通的 `def` 声明了路径操作。 +与其直接返回 `StreamingResponse`,更推荐遵循 [流式数据](./stream-data.md) 的写法,它更方便并在幕后为你处理取消。 + +如果你在流式传输 JSON Lines,请参阅教程:[流式传输 JSON Lines](../tutorial/stream-json-lines.md)。 /// @@ -267,11 +219,11 @@ FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它 你可以创建你自己的自定义响应类,继承自 `Response` 并使用它。 -例如,假设你想使用 `orjson`,但要使用内置 `ORJSONResponse` 类没有启用的一些自定义设置。 +例如,假设你想用一些设置来使用 [`orjson`](https://github.com/ijl/orjson)。 假设你想让它返回带缩进、格式化的 JSON,因此你想使用 orjson 选项 `orjson.OPT_INDENT_2`。 -你可以创建一个 `CustomORJSONResponse`。你需要做的主要事情是实现一个返回 `bytes` 的 `Response.render(content)` 方法: +你可以创建一个 `CustomORJSONResponse`。你需要做的主要事情是实现一个 `Response.render(content)` 方法,并返回 `bytes`: {* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} @@ -291,13 +243,21 @@ FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它 当然,你很可能会找到比格式化 JSON 更好的方式来利用这一点。😉 +### `orjson` 或响应模型 { #orjson-or-response-model } + +如果你追求的是性能,使用[响应模型](../tutorial/response-model.md) 往往比返回 `orjson` 响应更好。 + +使用响应模型时,FastAPI 会使用 Pydantic 直接把数据序列化为 JSON,不需要诸如通过 `jsonable_encoder` 转换这样的中间步骤(其他情况下会发生)。 + +并且在底层,Pydantic 使用与 `orjson` 相同的 Rust 机制来序列化 JSON,所以使用响应模型你已经可以获得最佳性能。 + ## 默认响应类 { #default-response-class } 在创建 **FastAPI** 类实例或 `APIRouter` 时,你可以指定默认要使用的响应类。 用于定义它的参数是 `default_response_class`。 -在下面的示例中,**FastAPI** 会在所有 *路径操作* 中默认使用 `ORJSONResponse`,而不是 `JSONResponse`。 +在下面的示例中,**FastAPI** 会在所有 *路径操作* 中默认使用 `HTMLResponse`,而不是 JSON。 {* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} @@ -309,4 +269,4 @@ FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它 ## 额外文档 { #additional-documentation } -你还可以使用 `responses` 在 OpenAPI 中声明媒体类型和许多其他详细信息:[OpenAPI 中的额外文档](additional-responses.md){.internal-link target=_blank}。 +你还可以使用 `responses` 在 OpenAPI 中声明媒体类型和许多其他详细信息:[OpenAPI 中的额外响应](additional-responses.md)。 diff --git a/docs/zh/docs/advanced/dataclasses.md b/docs/zh/docs/advanced/dataclasses.md index f552d779fb..42b4e4cc4d 100644 --- a/docs/zh/docs/advanced/dataclasses.md +++ b/docs/zh/docs/advanced/dataclasses.md @@ -2,11 +2,11 @@ FastAPI 基于 **Pydantic** 构建,我已经向你展示过如何使用 Pydantic 模型声明请求与响应。 -但 FastAPI 也支持以相同方式使用 `dataclasses`: +但 FastAPI 也支持以相同方式使用 [`dataclasses`](https://docs.python.org/3/library/dataclasses.html): {* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} -这仍然得益于 **Pydantic**,因为它对 `dataclasses` 的内置支持。 +这仍然得益于 **Pydantic**,因为它对 [`dataclasses` 的内置支持](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel)。 因此,即便上面的代码没有显式使用 Pydantic,FastAPI 也会使用 Pydantic 将那些标准数据类转换为 Pydantic 风格的 dataclasses。 @@ -67,7 +67,7 @@ FastAPI 基于 **Pydantic** 构建,我已经向你展示过如何使用 Pydant 一如既往,在 FastAPI 中你可以按需组合 `def` 和 `async def`。 - 如果需要回顾何时用哪一个,请查看关于 [`async` 和 `await`](../async.md#in-a-hurry){.internal-link target=_blank} 的文档中的 _“急不可待?”_ 一节。 + 如果需要回顾何时用哪一个,请查看关于 [`async` 和 `await`](../async.md#in-a-hurry) 的文档中的 _“急不可待?”_ 一节。 9. 这个 *路径操作函数* 返回的不是数据类(当然也可以返回数据类),而是包含内部数据的字典列表。 FastAPI 会使用(包含数据类的)`response_model` 参数来转换响应。 @@ -80,7 +80,7 @@ FastAPI 基于 **Pydantic** 构建,我已经向你展示过如何使用 Pydant 你还可以把 `dataclasses` 与其它 Pydantic 模型组合、从它们继承、把它们包含到你自己的模型中等。 -想了解更多,请查看 Pydantic 关于 dataclasses 的文档。 +想了解更多,请查看 [Pydantic 关于 dataclasses 的文档](https://docs.pydantic.dev/latest/concepts/dataclasses/)。 ## 版本 { #version } diff --git a/docs/zh/docs/advanced/events.md b/docs/zh/docs/advanced/events.md index 71ad1ae383..0b647a4388 100644 --- a/docs/zh/docs/advanced/events.md +++ b/docs/zh/docs/advanced/events.md @@ -150,11 +150,11 @@ async with lifespan(app): 只是为好奇者提供的技术细节。🤓 -在底层,这部分是 ASGI 技术规范中的 Lifespan 协议的一部分,定义了称为 `startup` 和 `shutdown` 的事件。 +在底层,这部分是 ASGI 技术规范中的 [Lifespan 协议](https://asgi.readthedocs.io/en/latest/specs/lifespan.html)的一部分,定义了称为 `startup` 和 `shutdown` 的事件。 /// info | 信息 -你可以在 Starlette 的 Lifespan 文档 中阅读更多关于 `lifespan` 处理器的内容。 +你可以在 [Starlette 的 Lifespan 文档](https://www.starlette.dev/lifespan/) 中阅读更多关于 `lifespan` 处理器的内容。 包括如何处理生命周期状态,以便在代码的其他部分使用。 @@ -162,4 +162,4 @@ async with lifespan(app): ## 子应用 { #sub-applications } -🚨 请注意,这些生命周期事件(startup 和 shutdown)只会在主应用上执行,不会在[子应用 - 挂载](sub-applications.md){.internal-link target=_blank}上执行。 +🚨 请注意,这些生命周期事件(startup 和 shutdown)只会在主应用上执行,不会在[子应用 - 挂载](sub-applications.md)上执行。 diff --git a/docs/zh/docs/advanced/generate-clients.md b/docs/zh/docs/advanced/generate-clients.md index e8a3b20558..5f53aa4347 100644 --- a/docs/zh/docs/advanced/generate-clients.md +++ b/docs/zh/docs/advanced/generate-clients.md @@ -8,11 +8,11 @@ ## 开源 SDK 生成器 { #open-source-sdk-generators } -一个功能多样的选择是 OpenAPI Generator,它支持**多种编程语言**,可以根据你的 OpenAPI 规范生成 SDK。 +一个功能多样的选择是 [OpenAPI Generator](https://openapi-generator.tech/),它支持**多种编程语言**,可以根据你的 OpenAPI 规范生成 SDK。 -对于 **TypeScript 客户端**,Hey API 是为 TypeScript 生态打造的专用方案,提供优化的使用体验。 +对于 **TypeScript 客户端**,[Hey API](https://heyapi.dev/) 是为 TypeScript 生态打造的专用方案,提供优化的使用体验。 -你还可以在 OpenAPI.Tools 上发现更多 SDK 生成器。 +你还可以在 [OpenAPI.Tools](https://openapi.tools/#sdk) 上发现更多 SDK 生成器。 /// tip | 提示 @@ -24,15 +24,15 @@ FastAPI 会自动生成 **OpenAPI 3.1** 规范,因此你使用的任何工具 本节介绍的是由赞助 FastAPI 的公司提供的、具备**风险投资背景**或**公司支持**的方案。这些产品在高质量生成的 SDK 之上,提供了**更多特性**和**集成**。 -通过 ✨ [**赞助 FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨,这些公司帮助确保框架及其**生态**保持健康并且**可持续**。 +通过 ✨ [**赞助 FastAPI**](../help-fastapi.md#sponsor-the-author) ✨,这些公司帮助确保框架及其**生态**保持健康并且**可持续**。 他们的赞助也体现了对 FastAPI **社区**(也就是你)的高度承诺,不仅关注提供**优秀的服务**,也支持一个**健壮且繁荣的框架**——FastAPI。🙇 例如,你可以尝试: -* Speakeasy -* Stainless -* liblab +* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) +* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) +* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) 其中一些方案也可能是开源的或提供免费层级,你可以不花钱就先试用。其他商业 SDK 生成器也可在网上找到。🤓 @@ -66,7 +66,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client 这会在 `./src/client` 生成一个 TypeScript SDK。 -你可以在其官网了解如何安装 `@hey-api/openapi-ts`,以及阅读生成结果的说明。 +你可以在其官网了解如何[安装 `@hey-api/openapi-ts`](https://heyapi.dev/openapi-ts/get-started),以及阅读[生成结果](https://heyapi.dev/openapi-ts/output)的说明。 ### 使用 SDK { #using-the-sdk } diff --git a/docs/zh/docs/advanced/index.md b/docs/zh/docs/advanced/index.md index 610c187137..24b4d076fc 100644 --- a/docs/zh/docs/advanced/index.md +++ b/docs/zh/docs/advanced/index.md @@ -2,13 +2,13 @@ ## 附加功能 { #additional-features } -主要的[教程 - 用户指南](../tutorial/index.md){.internal-link target=_blank}足以带你了解 **FastAPI** 的所有主要特性。 +主要的[教程 - 用户指南](../tutorial/index.md)足以带你了解 **FastAPI** 的所有主要特性。 在接下来的章节中,你将看到其他选项、配置和附加功能。 /// tip | 提示 -接下来的章节不一定是“高级”的。 +接下来的章节**不一定是“高级”的**。 对于你的用例,解决方案很可能就在其中之一。 @@ -16,6 +16,6 @@ ## 先阅读教程 { #read-the-tutorial-first } -仅凭主要[教程 - 用户指南](../tutorial/index.md){.internal-link target=_blank}中的知识,你已经可以使用 **FastAPI** 的大多数功能。 +仅凭主要[教程 - 用户指南](../tutorial/index.md)中的知识,你已经可以使用 **FastAPI** 的大多数功能。 接下来的章节默认你已经读过它,并理解其中的核心概念。 diff --git a/docs/zh/docs/advanced/middleware.md b/docs/zh/docs/advanced/middleware.md index de4a3fcb13..4077ec094c 100644 --- a/docs/zh/docs/advanced/middleware.md +++ b/docs/zh/docs/advanced/middleware.md @@ -1,8 +1,8 @@ # 高级中间件 { #advanced-middleware } -用户指南介绍了如何为应用添加[自定义中间件](../tutorial/middleware.md){.internal-link target=_blank} 。 +用户指南介绍了如何为应用添加[自定义中间件](../tutorial/middleware.md)。 -以及如何[使用 `CORSMiddleware` 处理 CORS](../tutorial/cors.md){.internal-link target=_blank}。 +以及如何[使用 `CORSMiddleware` 处理 CORS](../tutorial/cors.md)。 本章学习如何使用其它中间件。 @@ -87,11 +87,11 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") ## 其它中间件 { #other-middlewares } -除了上述中间件外,FastAPI 还支持其它ASGI 中间件。 +除了上述中间件外,FastAPI 还支持其它 ASGI 中间件。 例如: -* Uvicorn 的 `ProxyHeadersMiddleware` -* MessagePack +* [Uvicorn 的 `ProxyHeadersMiddleware`](https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py) +* [MessagePack](https://github.com/florimondmanca/msgpack-asgi) -其它可用中间件详见 Starlette 官档 - 中间件ASGI Awesome 列表。 +其它可用中间件详见 [Starlette 官档 - 中间件](https://www.starlette.dev/middleware/) 及 [ASGI Awesome 列表](https://github.com/florimondmanca/awesome-asgi)。 diff --git a/docs/zh/docs/advanced/openapi-callbacks.md b/docs/zh/docs/advanced/openapi-callbacks.md index cc9f5c28e1..49cef36481 100644 --- a/docs/zh/docs/advanced/openapi-callbacks.md +++ b/docs/zh/docs/advanced/openapi-callbacks.md @@ -35,7 +35,7 @@ API 的用户(外部开发者)要在您的 API 内使用 POST 请求创建 /// tip | 提示 -`callback_url` 查询参数使用 Pydantic 的 Url 类型。 +`callback_url` 查询参数使用 Pydantic 的 [Url](https://docs.pydantic.dev/latest/api/networks/) 类型。 /// @@ -66,7 +66,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) 实际的回调只是 HTTP 请求。 -实现回调时,要使用 HTTPXRequests。 +实现回调时,要使用 [HTTPX](https://www.python-httpx.org) 或 [Requests](https://requests.readthedocs.io/)。 /// @@ -106,13 +106,13 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) 回调*路径操作*与常规*路径操作*有两点主要区别: * 它不需要任何实际的代码,因为应用不会调用这段代码。它只是用于存档*外部 API*。因此,函数的内容只需要 `pass` 就可以了 -* *路径*可以包含 OpenAPI 3 表达式(详见下文),可以使用带参数的变量,以及发送至您的 API 的原始请求的部分 +* *路径*可以包含 [OpenAPI 3 表达式](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)(详见下文),可以使用带参数的变量,以及发送至您的 API 的原始请求的部分 ### 回调路径表达式 { #the-callback-path-expression } -回调*路径*支持包含发送给您的 API 的原始请求的部分的 OpenAPI 3 表达式。 +回调*路径*支持包含发送给您的 API 的原始请求的部分的 [OpenAPI 3 表达式](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)。 -本例中是**字符串**: +本例中是 `str`: ```Python "{$callback_url}/invoices/{$request.body.id}" @@ -173,13 +173,13 @@ JSON 请求体包含如下内容: /// tip | 提示 -注意,不能把路由本身(`invoices_callback_router`)传递给 `callback=`,要传递 `invoices_callback_router.routes` 中的 `.routes` 属性。 +注意,不能把路由本身(`invoices_callback_router`)传递给 `callbacks=`,要传递 `invoices_callback_router.routes` 中的 `.routes` 属性。 /// ### 查看文档 { #check-the-docs } -现在,启动应用并打开 http://127.0.0.1:8000/docs。 +现在,启动应用并打开 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 就能看到文档的*路径操作*已经包含了**回调**的内容以及*外部 API*: diff --git a/docs/zh/docs/advanced/openapi-webhooks.md b/docs/zh/docs/advanced/openapi-webhooks.md index d23fbcf888..3d6bcc9bc2 100644 --- a/docs/zh/docs/advanced/openapi-webhooks.md +++ b/docs/zh/docs/advanced/openapi-webhooks.md @@ -2,7 +2,7 @@ 有些情况下,您可能想告诉您的 API **用户**,您的应用程序可以携带一些数据调用*他们的*应用程序(给它们发送请求),通常是为了**通知**某种**事件**。 -这意味着,除了您的用户向您的 API 发送请求的一般情况,**您的 API**(或您的应用)也可以向**他们的系统**(他们的 API、他们的应用)**发送请求**。 +这意味着,与通常由您的用户向您的 API 发送请求的流程相反,是**您的 API**(或您的应用)可以**向他们的系统**(他们的 API、他们的应用)**发送请求**。 这通常被称为**网络钩子**(Webhook)。 @@ -48,7 +48,7 @@ ### 查看文档 { #check-the-docs } -现在您可以启动您的应用程序并访问 http://127.0.0.1:8000/docs. +现在您可以启动您的应用程序并访问 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 您会看到您的文档不仅有正常的*路径操作*显示,现在还多了一些**网络钩子**: diff --git a/docs/zh/docs/advanced/path-operation-advanced-configuration.md b/docs/zh/docs/advanced/path-operation-advanced-configuration.md index 588d4f09c5..67f3bd7e9a 100644 --- a/docs/zh/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/zh/docs/advanced/path-operation-advanced-configuration.md @@ -60,7 +60,7 @@ 你也可以为它声明带有各自模型、状态码等的附加响应。 -文档中有一个完整章节,你可以阅读这里的[OpenAPI 中的附加响应](additional-responses.md){.internal-link target=_blank}。 +文档中有一个完整章节,你可以阅读这里的[OpenAPI 中的附加响应](additional-responses.md)。 ## OpenAPI Extra { #openapi-extra } @@ -68,7 +68,7 @@ /// note | 技术细节 -在 OpenAPI 规范中,这被称为 Operation 对象。 +在 OpenAPI 规范中,这被称为 [Operation 对象](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object)。 /// @@ -82,7 +82,7 @@ 这是一个较低层级的扩展点。 -如果你只需要声明附加响应,更方便的方式是使用[OpenAPI 中的附加响应](additional-responses.md){.internal-link target=_blank}。 +如果你只需要声明附加响应,更方便的方式是使用[OpenAPI 中的附加响应](additional-responses.md)。 /// diff --git a/docs/zh/docs/advanced/response-change-status-code.md b/docs/zh/docs/advanced/response-change-status-code.md index 0b004bf4e5..379afd4eb9 100644 --- a/docs/zh/docs/advanced/response-change-status-code.md +++ b/docs/zh/docs/advanced/response-change-status-code.md @@ -1,6 +1,6 @@ # 响应 - 更改状态码 { #response-change-status-code } -你可能之前已经了解到,你可以设置默认的[响应状态码](../tutorial/response-status-code.md){.internal-link target=_blank}。 +你可能之前已经了解到,你可以设置默认的[响应状态码](../tutorial/response-status-code.md)。 但在某些情况下,你需要返回一个不同于默认值的状态码。 diff --git a/docs/zh/docs/advanced/response-cookies.md b/docs/zh/docs/advanced/response-cookies.md index c618cd0f0a..7fad89e5c6 100644 --- a/docs/zh/docs/advanced/response-cookies.md +++ b/docs/zh/docs/advanced/response-cookies.md @@ -18,7 +18,7 @@ 你还可以在直接响应`Response`时直接创建cookies。 -你可以参考[直接返回 Response](response-directly.md){.internal-link target=_blank}来创建response +为此,你可以按照[直接返回 Response](response-directly.md)中的说明创建一个响应。 然后设置Cookies,并返回: @@ -46,4 +46,4 @@ /// -如果你想查看所有可用的参数和选项,可以参考 Starlette帮助文档 +如果你想查看所有可用的参数和选项,可以参考 [Starlette 文档](https://www.starlette.dev/responses/#set-cookie)。 diff --git a/docs/zh/docs/advanced/response-directly.md b/docs/zh/docs/advanced/response-directly.md index a97992d249..1966221467 100644 --- a/docs/zh/docs/advanced/response-directly.md +++ b/docs/zh/docs/advanced/response-directly.md @@ -2,19 +2,24 @@ 当你创建一个 **FastAPI** *路径操作* 时,你可以正常返回以下任意一种数据:`dict`,`list`,Pydantic 模型,数据库模型等等。 -**FastAPI** 默认会使用 `jsonable_encoder` 将这些类型的返回值转换成 JSON 格式,`jsonable_encoder` 在 [JSON 兼容编码器](../tutorial/encoder.md){.internal-link target=_blank} 中有阐述。 +如果你声明了 [响应模型](../tutorial/response-model.md),FastAPI 会使用它通过 Pydantic 将数据序列化为 JSON。 +如果你没有声明响应模型,**FastAPI** 会使用在 [JSON 兼容编码器](../tutorial/encoder.md) 中阐述的 `jsonable_encoder`。 然后,**FastAPI** 会在后台将这些兼容 JSON 的数据(比如字典)放到一个 `JSONResponse` 中,该 `JSONResponse` 会用来发送响应给客户端。 但是你可以在你的 *路径操作* 中直接返回一个 `JSONResponse`。 -直接返回响应可能会有用处,比如返回自定义的响应头和 cookies。 +/// tip | 提示 + +通常使用 [响应模型](../tutorial/response-model.md) 会比直接返回 `JSONResponse` 拥有更好的性能,因为它会在 Rust 中使用 Pydantic 序列化数据。 + +/// ## 返回 `Response` { #return-a-response } 事实上,你可以返回任意 `Response` 或者任意 `Response` 的子类。 -/// tip | 提示 +/// info | 信息 `JSONResponse` 本身是一个 `Response` 的子类。 @@ -26,6 +31,8 @@ 这种特性给你极大的可扩展性。你可以返回任何数据类型,重写任何数据声明或者校验,等等。 +这也带来了很大的责任。你必须确保你返回的数据是正确的、格式正确、可被序列化,等等。 + ## 在 `Response` 中使用 `jsonable_encoder` { #using-the-jsonable-encoder-in-a-response } 由于 **FastAPI** 并未对你返回的 `Response` 做任何改变,你必须确保你已经准备好响应内容。 @@ -50,16 +57,28 @@ 现在,让我们看看你如何才能返回一个自定义的响应。 -假设你想要返回一个 XML 响应。 +假设你想要返回一个 [XML](https://en.wikipedia.org/wiki/XML) 响应。 你可以把你的 XML 内容放到一个字符串中,放到一个 `Response` 中,然后返回: {* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} +## 响应模型如何工作 { #how-a-response-model-works } + +当你在路径操作中声明一个 [响应模型 - 返回类型](../tutorial/response-model.md) 时,**FastAPI** 会使用它通过 Pydantic 将数据序列化为 JSON。 + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +由于这些工作会在 Rust 侧完成,性能将比在常规 Python 中配合 `JSONResponse` 类完成要好得多。 + +当使用 `response_model` 或返回类型时,FastAPI 不会使用 `jsonable_encoder` 来转换数据(那样会更慢),也不会使用 `JSONResponse` 类。 + +相反,它会采用使用该响应模型(或返回类型)由 Pydantic 生成的 JSON 字节,并直接返回一个具有正确 JSON 媒体类型(`application/json`)的 `Response`。 + ## 说明 { #notes } 当你直接返回 `Response` 时,它的数据既没有校验,又不会进行转换(序列化),也不会自动生成文档。 -但是你仍可以参考 [OpenAPI 中的额外响应](additional-responses.md){.internal-link target=_blank} 给响应编写文档。 +但是你仍可以参考 [OpenAPI 中的额外响应](additional-responses.md) 给响应编写文档。 在后续的章节中你可以了解到如何使用/声明这些自定义的 `Response` 的同时还保留自动化的数据转换和文档等。 diff --git a/docs/zh/docs/advanced/response-headers.md b/docs/zh/docs/advanced/response-headers.md index 01bde56d2a..ab99a4ece1 100644 --- a/docs/zh/docs/advanced/response-headers.md +++ b/docs/zh/docs/advanced/response-headers.md @@ -20,7 +20,7 @@ 你也可以在直接返回 `Response` 时添加头部。 -按照[直接返回响应](response-directly.md){.internal-link target=_blank}中所述创建响应,并将头部作为附加参数传递: +按照[直接返回响应](response-directly.md)中所述创建响应,并将头部作为附加参数传递: {* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} @@ -36,6 +36,6 @@ ## 自定义头部 { #custom-headers } -请注意,可以通过使用 `X-` 前缀添加自定义专有头部。 +请注意,可以通过[使用 `X-` 前缀](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)添加自定义专有头部。 -但是,如果你有自定义头部,并希望浏览器中的客户端能够看到它们,你需要将它们添加到你的 CORS 配置中(在 [CORS(跨源资源共享)](../tutorial/cors.md){.internal-link target=_blank} 中阅读更多),使用在 Starlette 的 CORS 文档中记录的 `expose_headers` 参数。 +但是,如果你有自定义头部,并希望浏览器中的客户端能够看到它们,你需要将它们添加到你的 CORS 配置中(在 [CORS(跨源资源共享)](../tutorial/cors.md) 中阅读更多),使用在 [Starlette 的 CORS 文档](https://www.starlette.dev/middleware/#corsmiddleware)中记录的 `expose_headers` 参数。 diff --git a/docs/zh/docs/advanced/security/http-basic-auth.md b/docs/zh/docs/advanced/security/http-basic-auth.md index 9128a49753..37e4b5abcb 100644 --- a/docs/zh/docs/advanced/security/http-basic-auth.md +++ b/docs/zh/docs/advanced/security/http-basic-auth.md @@ -32,7 +32,7 @@ HTTP 基础授权让浏览器显示内置的用户名与密码提示。 使用依赖项检查用户名与密码是否正确。 -为此要使用 Python 标准模块 `secrets` 检查用户名与密码。 +为此要使用 Python 标准模块 [`secrets`](https://docs.python.org/3/library/secrets.html) 检查用户名与密码。 `secrets.compare_digest()` 需要仅包含 ASCII 字符(英语字符)的 `bytes` 或 `str`,这意味着它不适用于像`á`一样的字符,如 `Sebastián`。 diff --git a/docs/zh/docs/advanced/security/index.md b/docs/zh/docs/advanced/security/index.md index 84fec7aab8..e3a3ba9cea 100644 --- a/docs/zh/docs/advanced/security/index.md +++ b/docs/zh/docs/advanced/security/index.md @@ -2,7 +2,7 @@ ## 附加特性 { #additional-features } -除 [教程 - 用户指南: 安全性](../../tutorial/security/index.md){.internal-link target=_blank} 中涵盖的功能之外,还有一些额外的功能来处理安全性。 +除 [教程 - 用户指南: 安全性](../../tutorial/security/index.md) 中涵盖的功能之外,还有一些额外的功能来处理安全性。 /// tip | 提示 @@ -14,6 +14,6 @@ ## 先阅读教程 { #read-the-tutorial-first } -接下来的部分假设你已经阅读了主要的 [教程 - 用户指南: 安全性](../../tutorial/security/index.md){.internal-link target=_blank}。 +接下来的部分假设你已经阅读了主要的 [教程 - 用户指南: 安全性](../../tutorial/security/index.md)。 它们都基于相同的概念,但支持一些额外的功能。 diff --git a/docs/zh/docs/advanced/security/oauth2-scopes.md b/docs/zh/docs/advanced/security/oauth2-scopes.md index ce7facf4be..a1ecc641ca 100644 --- a/docs/zh/docs/advanced/security/oauth2-scopes.md +++ b/docs/zh/docs/advanced/security/oauth2-scopes.md @@ -60,7 +60,7 @@ OAuth2 规范将“作用域”定义为由空格分隔的字符串列表。 ## 全局纵览 { #global-view } -首先,让我们快速看看与**用户指南**中 [OAuth2 实现密码(含哈希)、Bearer + JWT 令牌](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank} 示例相比有哪些变化。现在开始使用 OAuth2 作用域: +首先,让我们快速看看与**用户指南**中 [OAuth2 实现密码(含哈希)、Bearer + JWT 令牌](../../tutorial/security/oauth2-jwt.md) 示例相比有哪些变化。现在开始使用 OAuth2 作用域: {* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} @@ -271,4 +271,4 @@ OAuth2 规范将“作用域”定义为由空格分隔的字符串列表。 ## 装饰器 `dependencies` 中的 `Security` { #security-in-decorator-dependencies } -就像你可以在装饰器的 `dependencies` 参数中定义 `Depends` 的 `list`(详见[路径操作装饰器依赖项](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}),你也可以在那儿配合 `Security` 使用 `scopes`。 +就像你可以在装饰器的 `dependencies` 参数中定义 `Depends` 的 `list`(详见[路径操作装饰器依赖项](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md)),你也可以在那儿配合 `Security` 使用 `scopes`。 diff --git a/docs/zh/docs/advanced/settings.md b/docs/zh/docs/advanced/settings.md index b4def73eb5..31a7cc82de 100644 --- a/docs/zh/docs/advanced/settings.md +++ b/docs/zh/docs/advanced/settings.md @@ -8,7 +8,7 @@ /// tip | 提示 -要理解环境变量,你可以阅读[环境变量](../environment-variables.md){.internal-link target=_blank}。 +要理解环境变量,你可以阅读[环境变量](../environment-variables.md)。 /// @@ -20,11 +20,11 @@ ## Pydantic 的 `Settings` { #pydantic-settings } -幸运的是,Pydantic 提供了一个很好的工具来处理来自环境变量的这些设置:Pydantic: Settings management。 +幸运的是,Pydantic 提供了一个很好的工具来处理来自环境变量的这些设置:[Pydantic:Settings 管理](https://docs.pydantic.dev/latest/concepts/pydantic_settings/)。 ### 安装 `pydantic-settings` { #install-pydantic-settings } -首先,确保你创建并激活了[虚拟环境](../virtual-environments.md){.internal-link target=_blank},然后安装 `pydantic-settings` 包: +首先,确保你创建并激活了[虚拟环境](../virtual-environments.md),然后安装 `pydantic-settings` 包:
@@ -100,7 +100,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p ## 在另一个模块中放置设置 { #settings-in-another-module } -你可以把这些设置放在另一个模块文件中,就像你在[更大的应用 - 多个文件](../tutorial/bigger-applications.md){.internal-link target=_blank}中看到的那样。 +你可以把这些设置放在另一个模块文件中,就像你在[更大的应用 - 多个文件](../tutorial/bigger-applications.md)中看到的那样。 例如,可以有一个 `config.py` 文件: @@ -112,7 +112,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p /// tip | 提示 -你还需要一个 `__init__.py` 文件,就像你在[更大的应用 - 多个文件](../tutorial/bigger-applications.md){.internal-link target=_blank}中看到的那样。 +你还需要一个 `__init__.py` 文件,就像你在[更大的应用 - 多个文件](../tutorial/bigger-applications.md)中看到的那样。 /// @@ -172,7 +172,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p /// -Pydantic 支持使用一个外部库来从这类文件中读取。你可以在 Pydantic Settings: Dotenv (.env) support 中阅读更多信息。 +Pydantic 支持使用一个外部库来从这类文件中读取。你可以在 [Pydantic Settings:Dotenv(.env)支持](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support) 中阅读更多信息。 /// tip | 提示 @@ -197,7 +197,7 @@ APP_NAME="ChimichangApp" /// tip | 提示 -`model_config` 属性仅用于 Pydantic 配置。你可以在 Pydantic: Concepts: Configuration 中阅读更多信息。 +`model_config` 属性仅用于 Pydantic 配置。你可以在 [Pydantic:概念:配置](https://docs.pydantic.dev/latest/concepts/config/) 中阅读更多信息。 /// @@ -291,7 +291,7 @@ participant execute as Execute function 这样,它的行为几乎就像是一个全局变量。但由于它使用了依赖项函数,我们可以在测试时很容易地覆盖它。 -`@lru_cache` 是 `functools` 的一部分,它属于 Python 标准库。你可以在 Python 文档中关于 `@lru_cache` 的章节阅读更多信息。 +`@lru_cache` 是 `functools` 的一部分,它属于 Python 标准库。你可以在 [Python 文档中关于 `@lru_cache` 的章节](https://docs.python.org/3/library/functools.html#functools.lru_cache)阅读更多信息。 ## 小结 { #recap } diff --git a/docs/zh/docs/advanced/sub-applications.md b/docs/zh/docs/advanced/sub-applications.md index 3e61610a37..b0230402bf 100644 --- a/docs/zh/docs/advanced/sub-applications.md +++ b/docs/zh/docs/advanced/sub-applications.md @@ -30,25 +30,25 @@ ### 查看自动 API 文档 { #check-the-automatic-api-docs } -现在,使用你的文件运行 `fastapi` 命令: +现在,运行 `fastapi` 命令:
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-然后在 http://127.0.0.1:8000/docs 打开文档。 +然后在 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) 打开文档。 下图显示的是主应用 API 文档,只包括其自有的*路径操作*。 -然后查看子应用文档 http://127.0.0.1:8000/subapi/docs。 +然后查看子应用文档 [http://127.0.0.1:8000/subapi/docs](http://127.0.0.1:8000/subapi/docs)。 下图显示的是子应用的 API 文档,也是只包括其自有的*路径操作*,所有这些路径操作都在 `/subapi` 子路径前缀下。 @@ -64,4 +64,4 @@ $ fastapi dev main.py 并且子应用还可以再挂载子应用,一切都会正常运行,FastAPI 可以自动处理所有 `root_path`。 -关于 `root_path` 及如何显式使用 `root_path` 的内容,详见[使用代理](behind-a-proxy.md){.internal-link target=_blank}一章。 +关于 `root_path` 及如何显式使用 `root_path` 的内容,详见[使用代理](behind-a-proxy.md)一章。 diff --git a/docs/zh/docs/advanced/templates.md b/docs/zh/docs/advanced/templates.md index 37575aff29..952f438c73 100644 --- a/docs/zh/docs/advanced/templates.md +++ b/docs/zh/docs/advanced/templates.md @@ -8,7 +8,7 @@ Flask 等工具使用的 Jinja2 是最用的模板引擎。 ## 安装依赖项 { #install-dependencies } -确保你创建一个[虚拟环境](../virtual-environments.md){.internal-link target=_blank},激活它,并安装 `jinja2`: +确保你创建一个[虚拟环境](../virtual-environments.md),激活它,并安装 `jinja2`:
@@ -29,14 +29,14 @@ $ pip install jinja2 {* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} -/// note +/// note | 注意 在 FastAPI 0.108.0,Starlette 0.29.0 之前,`name` 是第一个参数。 并且,在此之前,`request` 对象是作为 context 的一部分以键值对的形式传递的。 /// -/// tip +/// tip | 提示 通过声明 `response_class=HTMLResponse`,API 文档就能识别响应的对象是 HTML。 @@ -122,4 +122,4 @@ Item ID: 42 ## 更多说明 { #more-details } -包括测试模板等更多详情,请参阅 Starlette 官方文档 - 模板。 +包括如何测试模板在内的更多详情,请查看 [Starlette 的模板文档](https://www.starlette.dev/templates/)。 diff --git a/docs/zh/docs/advanced/testing-websockets.md b/docs/zh/docs/advanced/testing-websockets.md index e435e41e23..6d2e4b0988 100644 --- a/docs/zh/docs/advanced/testing-websockets.md +++ b/docs/zh/docs/advanced/testing-websockets.md @@ -8,6 +8,6 @@ /// note | 注意 -更多细节请查看 Starlette 的文档:测试 WebSockets。 +更多细节请查看 Starlette 的文档:[测试 WebSockets](https://www.starlette.dev/testclient/#testing-websocket-sessions)。 /// diff --git a/docs/zh/docs/advanced/using-request-directly.md b/docs/zh/docs/advanced/using-request-directly.md index 8cfad4203a..519443d9d2 100644 --- a/docs/zh/docs/advanced/using-request-directly.md +++ b/docs/zh/docs/advanced/using-request-directly.md @@ -15,7 +15,7 @@ ## `Request` 对象的细节 { #details-about-the-request-object } -实际上,**FastAPI** 的底层是 **Starlette**,**FastAPI** 只不过是在 **Starlette** 顶层提供了一些工具,所以能直接使用 Starlette 的 `Request` 对象。 +实际上,**FastAPI** 的底层是 **Starlette**,**FastAPI** 只不过是在 **Starlette** 顶层提供了一些工具,所以能直接使用 Starlette 的 [`Request`](https://www.starlette.dev/requests/) 对象。 但直接从 `Request` 对象提取数据时(例如,读取请求体),这些数据不会被 **FastAPI** 验证、转换或文档化(使用 OpenAPI,为自动的 API 用户界面)。 @@ -45,7 +45,7 @@ ## `Request` 文档 { #request-documentation } -更多细节详见 Starlette 官档 - `Request` 对象。 +你可以在[Starlette 官方文档站点的 `Request` 对象](https://www.starlette.dev/requests/)中阅读更多细节。 /// note | 技术细节 diff --git a/docs/zh/docs/advanced/websockets.md b/docs/zh/docs/advanced/websockets.md index a4cdae3a22..d90ef87339 100644 --- a/docs/zh/docs/advanced/websockets.md +++ b/docs/zh/docs/advanced/websockets.md @@ -1,10 +1,10 @@ # WebSockets { #websockets } -您可以在 **FastAPI** 中使用 WebSockets。 +您可以在 **FastAPI** 中使用 [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)。 ## 安装 `websockets` { #install-websockets } -请确保您创建一个[虚拟环境](../virtual-environments.md){.internal-link target=_blank}、激活它,并安装 `websockets`(一个让使用“WebSocket”协议更容易的 Python 库): +请确保您创建一个[虚拟环境](../virtual-environments.md)、激活它,并安装 `websockets`(一个让使用“WebSocket”协议更容易的 Python 库):
@@ -64,19 +64,19 @@ $ pip install websockets ## 尝试一下 { #try-it } -如果您的文件名为 `main.py`,请使用以下命令运行应用程序: +将代码放在 `main.py`,然后运行你的应用程序:
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-在浏览器中打开 http://127.0.0.1:8000。 +在浏览器中打开 [http://127.0.0.1:8000](http://127.0.0.1:8000)。 您将看到一个简单的页面,如下所示: @@ -86,7 +86,7 @@ $ fastapi dev main.py -您的 **FastAPI** 应用程序将回复: +您的 **FastAPI** 应用程序将通过 WebSockets 回复: @@ -115,25 +115,25 @@ $ fastapi dev main.py 由于这是一个 WebSocket,抛出 `HTTPException` 并不是很合理,而是抛出 `WebSocketException`。 -您可以使用规范中定义的有效代码。 +您可以使用[规范中定义的有效代码](https://tools.ietf.org/html/rfc6455#section-7.4.1)。 /// ### 尝试带有依赖项的 WebSockets { #try-the-websockets-with-dependencies } -如果您的文件名为 `main.py`,请使用以下命令运行应用程序: +运行你的应用程序:
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-在浏览器中打开 http://127.0.0.1:8000。 +在浏览器中打开 [http://127.0.0.1:8000](http://127.0.0.1:8000)。 在页面中,您可以设置: @@ -174,7 +174,7 @@ Client #1596980209979 left the chat 但请记住,由于所有内容都在内存中以单个列表的形式处理,因此它只能在进程运行时工作,并且只能使用单个进程。 -如果您需要与 FastAPI 集成更简单但更强大的功能,支持 Redis、PostgreSQL 或其他功能,请查看 encode/broadcaster。 +如果您需要与 FastAPI 集成更简单但更强大的功能,支持 Redis、PostgreSQL 或其他功能,请查看 [encode/broadcaster](https://github.com/encode/broadcaster)。 /// @@ -182,5 +182,5 @@ Client #1596980209979 left the chat 要了解更多选项,请查看 Starlette 的文档: -* `WebSocket` 类。 -* 基于类的 WebSocket 处理。 +* [`WebSocket` 类](https://www.starlette.dev/websockets/)。 +* [基于类的 WebSocket 处理](https://www.starlette.dev/endpoints/#websocketendpoint)。 diff --git a/docs/zh/docs/advanced/wsgi.md b/docs/zh/docs/advanced/wsgi.md index 487fbf8ddb..038b672f8a 100644 --- a/docs/zh/docs/advanced/wsgi.md +++ b/docs/zh/docs/advanced/wsgi.md @@ -1,6 +1,6 @@ # 包含 WSGI - Flask,Django,其它 { #including-wsgi-flask-django-others } -您可以挂载 WSGI 应用,正如您在 [子应用 - 挂载](sub-applications.md){.internal-link target=_blank}、[在代理之后](behind-a-proxy.md){.internal-link target=_blank} 中所看到的那样。 +您可以挂载 WSGI 应用,正如您在 [子应用 - 挂载](sub-applications.md)、[在代理之后](behind-a-proxy.md) 中所看到的那样。 为此, 您可以使用 `WSGIMiddleware` 来包装你的 WSGI 应用,如:Flask,Django,等等。 @@ -36,13 +36,13 @@ 其余的请求则会被 **FastAPI** 处理。 -如果你运行它并访问 http://localhost:8000/v1/,你将会看到由 Flask 返回的响应: +如果你运行它并访问 [http://localhost:8000/v1/](http://localhost:8000/v1/),你将会看到由 Flask 返回的响应: ```txt Hello, World from Flask! ``` -如果你访问 http://localhost:8000/v2,你将会看到由 FastAPI 返回的响应: +如果你访问 [http://localhost:8000/v2](http://localhost:8000/v2),你将会看到由 FastAPI 返回的响应: ```JSON { diff --git a/docs/zh/docs/alternatives.md b/docs/zh/docs/alternatives.md index 8a552c91d4..fe7aa98698 100644 --- a/docs/zh/docs/alternatives.md +++ b/docs/zh/docs/alternatives.md @@ -14,7 +14,7 @@ ## 先前的工具 { #previous-tools } -### Django { #django } +### [Django](https://www.djangoproject.com/) { #django } 它是最流行且被广泛信任的 Python 框架。被用于构建 Instagram 等系统。 @@ -22,7 +22,7 @@ 它最初用于在后端生成 HTML,而不是创建由现代前端(如 React、Vue.js、Angular)或与之通信的其他系统(如 IoT 设备)使用的 API。 -### Django REST Framework { #django-rest-framework } +### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } Django REST framework 作为一个灵活工具箱而创建,用于在底层使用 Django 构建 Web API,从而增强其 API 能力。 @@ -42,7 +42,7 @@ Django REST Framework 由 Tom Christie 创建。他也是 Starlette 和 Uvicorn /// -### Flask { #flask } +### [Flask](https://flask.palletsprojects.com) { #flask } Flask 是一个“微框架”,它不包含数据库集成,也没有像 Django 那样的许多默认内建功能。 @@ -63,7 +63,7 @@ Flask 是一个“微框架”,它不包含数据库集成,也没有像 Djan /// -### Requests { #requests } +### [Requests](https://requests.readthedocs.io) { #requests } **FastAPI** 实际上不是 **Requests** 的替代品。它们的作用范围完全不同。 @@ -99,13 +99,13 @@ def read_url(): /// check | 启发 **FastAPI**: -- 提供简单直观的 API。 -- 直接、自然地使用 HTTP 方法名(操作)。 -- 具备合理默认值,同时支持强大定制能力。 +* 提供简单直观的 API。 +* 直接、自然地使用 HTTP 方法名(操作)。 +* 具备合理默认值,同时支持强大定制能力。 /// -### Swagger / OpenAPI { #swagger-openapi } +### [Swagger](https://swagger.io/) / [OpenAPI](https://github.com/OAI/OpenAPI-Specification/) { #swagger-openapi } 我想从 Django REST Framework 得到的主要特性之一是自动 API 文档。 @@ -123,8 +123,8 @@ def read_url(): 并集成基于标准的用户界面工具: -- Swagger UI -- ReDoc +* [Swagger UI](https://github.com/swagger-api/swagger-ui) +* [ReDoc](https://github.com/Rebilly/ReDoc) 选择这两者是因为它们相当流行且稳定;但稍作搜索,你就能找到数十种 OpenAPI 的替代用户界面(都可以与 **FastAPI** 搭配使用)。 @@ -134,7 +134,7 @@ def read_url(): 有若干基于 Flask 的 REST 框架,但在投入时间精力深入调研后,我发现许多已停止维护或被弃用,并存在多处未解决问题,不太适合采用。 -### Marshmallow { #marshmallow } +### [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) { #marshmallow } API 系统所需的主要特性之一是数据“序列化”,即将代码(Python)中的数据转换为可通过网络发送的形式。例如,将包含数据库数据的对象转换为 JSON 对象、将 `datetime` 对象转换为字符串等。 @@ -152,7 +152,7 @@ API 的另一个重要特性是数据校验,确保数据在给定约束下是 /// -### Webargs { #webargs } +### [Webargs](https://webargs.readthedocs.io/en/latest/) { #webargs } API 的另一个重要需求是从传入请求中解析数据。 @@ -174,7 +174,7 @@ Webargs 由与 Marshmallow 相同的开发者创建。 /// -### APISpec { #apispec } +### [APISpec](https://apispec.readthedocs.io/en/stable/) { #apispec } Marshmallow 与 Webargs 通过插件提供了校验、解析与序列化。 @@ -204,7 +204,7 @@ APISpec 由与 Marshmallow 相同的开发者创建。 /// -### Flask-apispec { #flask-apispec } +### [Flask-apispec](https://flask-apispec.readthedocs.io/en/latest/) { #flask-apispec } 这是一个 Flask 插件,将 Webargs、Marshmallow 与 APISpec 结合在一起。 @@ -218,11 +218,11 @@ APISpec 由与 Marshmallow 相同的开发者创建。 使用它促成了若干 Flask 全栈脚手架的诞生。以下是我(以及若干外部团队)至今使用的主要技术栈: -* https://github.com/tiangolo/full-stack -* https://github.com/tiangolo/full-stack-flask-couchbase -* https://github.com/tiangolo/full-stack-flask-couchdb +* [https://github.com/tiangolo/full-stack](https://github.com/tiangolo/full-stack) +* [https://github.com/tiangolo/full-stack-flask-couchbase](https://github.com/tiangolo/full-stack-flask-couchbase) +* [https://github.com/tiangolo/full-stack-flask-couchdb](https://github.com/tiangolo/full-stack-flask-couchdb) -这些全栈脚手架也成为了[**FastAPI** 项目脚手架](project-generation.md){.internal-link target=_blank}的基础。 +这些全栈脚手架也成为了[**FastAPI** 项目脚手架](project-generation.md)的基础。 /// info | 信息 @@ -236,7 +236,7 @@ Flask-apispec 由与 Marshmallow 相同的开发者创建。 /// -### NestJS(以及 Angular) { #nestjs-and-angular } +### [NestJS](https://nestjs.com/)(以及 [Angular](https://angular.io/)) { #nestjs-and-angular } 这甚至不是 Python。NestJS 是一个 JavaScript(TypeScript)的 NodeJS 框架,受 Angular 启发。 @@ -258,13 +258,13 @@ Flask-apispec 由与 Marshmallow 相同的开发者创建。 /// -### Sanic { #sanic } +### [Sanic](https://sanic.readthedocs.io/en/latest/) { #sanic } 它是最早的一批基于 `asyncio` 的极速 Python 框架之一,且做得与 Flask 很相似。 /// note | 技术细节 -它使用了 `uvloop` 来替代 Python 默认的 `asyncio` 循环。这正是它如此之快的原因。 +它使用了 [`uvloop`](https://github.com/MagicStack/uvloop) 来替代 Python 默认的 `asyncio` 循环。这正是它如此之快的原因。 它显然启发了 Uvicorn 和 Starlette;在公开的基准测试中,它们目前比 Sanic 更快。 @@ -278,7 +278,7 @@ Flask-apispec 由与 Marshmallow 相同的开发者创建。 /// -### Falcon { #falcon } +### [Falcon](https://falconframework.org/) { #falcon } Falcon 是另一个高性能 Python 框架,它被设计为精简且可作为 Hug 等其他框架的基础。 @@ -294,7 +294,7 @@ Falcon 是另一个高性能 Python 框架,它被设计为精简且可作为 H /// -### Molten { #molten } +### [Molten](https://moltenframework.com/) { #molten } 我在构建 **FastAPI** 的早期阶段发现了 Molten。它有不少相似的想法: @@ -318,7 +318,7 @@ Falcon 是另一个高性能 Python 框架,它被设计为精简且可作为 H /// -### Hug { #hug } +### [Hug](https://github.com/hugapi/hug) { #hug } Hug 是最早使用 Python 类型提示来声明 API 参数类型的框架之一。这一绝妙想法也启发了其他工具。 @@ -334,7 +334,7 @@ Hug 是最早使用 Python 类型提示来声明 API 参数类型的框架之一 /// info | 信息 -Hug 由 Timothy Crosley 创建,他也是 `isort` 的作者,这是一个能自动排序 Python 文件中导入的优秀工具。 +Hug 由 Timothy Crosley 创建,他也是 [`isort`](https://github.com/timothycrosley/isort) 的作者,这是一个能自动排序 Python 文件中导入的优秀工具。 /// @@ -348,7 +348,7 @@ Hug 启发 **FastAPI** 在函数中声明 `response` 参数,用于设置 heade /// -### APIStar (<= 0.5) { #apistar-0-5 } +### [APIStar](https://github.com/encode/apistar) (<= 0.5) { #apistar-0-5 } 就在决定动手构建 **FastAPI** 之前,我找到了 **APIStar** 服务器。它几乎具备我想要的一切,设计也很出色。 @@ -398,7 +398,7 @@ APIStar 由 Tom Christie 创建。他还创建了: ## **FastAPI** 所使用的组件 { #used-by-fastapi } -### Pydantic { #pydantic } +### [Pydantic](https://docs.pydantic.dev/) { #pydantic } Pydantic 是一个基于 Python 类型提示来定义数据校验、序列化与文档(使用 JSON Schema)的库。 @@ -414,7 +414,7 @@ Pydantic 是一个基于 Python 类型提示来定义数据校验、序列化与 /// -### Starlette { #starlette } +### [Starlette](https://www.starlette.dev/) { #starlette } Starlette 是一个轻量级的 ASGI 框架/工具集,非常适合构建高性能的 asyncio 服务。 @@ -459,7 +459,7 @@ ASGI 是由 Django 核心团队成员推动的新“标准”。它尚不是正 /// -### Uvicorn { #uvicorn } +### [Uvicorn](https://www.uvicorn.dev/) { #uvicorn } Uvicorn 是一个基于 uvloop 与 httptools 构建的极速 ASGI 服务器。 @@ -473,10 +473,10 @@ Uvicorn 是一个基于 uvloop 与 httptools 构建的极速 ASGI 服务器。 你也可以使用 `--workers` 命令行选项以获得异步的多进程服务器。 -更多细节见[部署](deployment/index.md){.internal-link target=_blank}一节。 +更多细节见[部署](deployment/index.md)一节。 /// ## 基准与速度 { #benchmarks-and-speed } -要理解、比较并查看 Uvicorn、Starlette 与 FastAPI 之间的差异,请查看[基准](benchmarks.md){.internal-link target=_blank}一节。 +要理解、比较并查看 Uvicorn、Starlette 与 FastAPI 之间的差异,请查看[基准](benchmarks.md)一节。 diff --git a/docs/zh/docs/async.md b/docs/zh/docs/async.md index 36d875f515..92ee5ef22f 100644 --- a/docs/zh/docs/async.md +++ b/docs/zh/docs/async.md @@ -141,7 +141,7 @@ Python 的现代版本支持通过一种叫**"协程"**——使用 `async` 和 /// info | 信息 -漂亮的插画来自 Ketrina Thompson. 🎨 +漂亮的插画来自 [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot)。🎨 /// @@ -207,7 +207,7 @@ Python 的现代版本支持通过一种叫**"协程"**——使用 `async` 和 /// info | 信息 -漂亮的插画来自 Ketrina Thompson. 🎨 +漂亮的插画来自 [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot)。🎨 /// @@ -251,7 +251,7 @@ Python 的现代版本支持通过一种叫**"协程"**——使用 `async` 和 这与 **FastAPI** 的性能水平相同。 -你可以同时拥有并行性和异步性,你可以获得比大多数经过测试的 NodeJS 框架更高的性能,并且与 Go 不相上下, Go 是一种更接近于 C 的编译语言(全部归功于 Starlette)。 +你可以同时拥有并行性和异步性,你可以获得比大多数经过测试的 NodeJS 框架更高的性能,并且与 Go 不相上下, Go 是一种更接近于 C 的编译语言([全部归功于 Starlette](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1))。 ### 并发比并行好吗? { #is-concurrency-better-than-parallelism } @@ -298,7 +298,7 @@ CPU 密集型操作的常见示例是需要复杂的数学处理。 这一点,再加上 Python 是**数据科学**、机器学习(尤其是深度学习)的主要语言这一简单事实,使得 **FastAPI** 与数据科学/机器学习 Web API 和应用程序(以及其他许多应用程序)非常匹配。 -了解如何在生产环境中实现这种并行性,可查看此文 [部署](deployment/index.md){.internal-link target=_blank}。 +了解如何在生产环境中实现这种并行性,可查看此文 [部署](deployment/index.md)。 ## `async` 和 `await` { #async-and-await } @@ -363,13 +363,13 @@ async def read_burgers(): ### 编写自己的异步代码 { #write-your-own-async-code } -Starlette (和 **FastAPI**) 是基于 AnyIO 实现的,这使得它们可以兼容 Python 的标准库 asyncioTrio。 +Starlette (和 **FastAPI**) 是基于 [AnyIO](https://anyio.readthedocs.io/en/stable/) 实现的,这使得它们可以兼容 Python 的标准库 [asyncio](https://docs.python.org/3/library/asyncio-task.html) 和 [Trio](https://trio.readthedocs.io/en/stable/)。 -特别是,你可以直接使用 AnyIO 来处理高级的并发用例,这些用例需要在自己的代码中使用更高级的模式。 +特别是,你可以直接使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 来处理高级的并发用例,这些用例需要在自己的代码中使用更高级的模式。 -即使你没有使用 **FastAPI**,你也可以使用 AnyIO 编写自己的异步程序,使其拥有较高的兼容性并获得一些好处(例如, 结构化并发)。 +即使你没有使用 **FastAPI**,你也可以使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 编写自己的异步程序,使其拥有较高的兼容性并获得一些好处(例如, 结构化并发)。 -我基于 AnyIO 新建了一个库,作为一个轻量级的封装层,用来优化类型注解,同时提供了更好的**自动补全**、**内联错误提示**等功能。这个库还附带了一个友好的入门指南和教程,能帮助你**理解**并编写**自己的异步代码**:Asyncer。如果你有**结合使用异步代码和常规**(阻塞/同步)代码的需求,这个库会特别有用。 +我基于 AnyIO 新建了一个库,作为一个轻量级的封装层,用来优化类型注解,同时提供了更好的**自动补全**、**内联错误提示**等功能。这个库还附带了一个友好的入门指南和教程,能帮助你**理解**并编写**自己的异步代码**:[Asyncer](https://asyncer.tiangolo.com/)。如果你有**结合使用异步代码和常规**(阻塞/同步)代码的需求,这个库会特别有用。 ### 其他形式的异步代码 { #other-forms-of-asynchronous-code } @@ -381,7 +381,7 @@ Starlette (和 **FastAPI**) 是基于 Gevent。但代码的理解、调试和思考都要复杂许多。 +在以前版本的 Python,你可以使用多线程或者 [Gevent](https://www.gevent.org/)。但代码的理解、调试和思考都要复杂许多。 在以前版本的 NodeJS / 浏览器 JavaScript 中,你会使用"回调",因此也可能导致“回调地狱”。 @@ -419,15 +419,15 @@ Starlette (和 **FastAPI**) 是基于 I/O 的代码。 -在这两种情况下,与你之前的框架相比,**FastAPI** 可能[仍然很快](index.md#performance){.internal-link target=_blank}。 +在这两种情况下,与你之前的框架相比,**FastAPI** 可能[仍然很快](index.md#performance)。 ### 依赖 { #dependencies } -这同样适用于[依赖](tutorial/dependencies/index.md){.internal-link target=_blank}。如果一个依赖是标准的 `def` 函数而不是 `async def`,它将被运行在外部线程池中。 +这同样适用于[依赖](tutorial/dependencies/index.md)。如果一个依赖是标准的 `def` 函数而不是 `async def`,它将被运行在外部线程池中。 ### 子依赖 { #sub-dependencies } -你可以拥有多个相互依赖的依赖以及[子依赖](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} (作为函数的参数),它们中的一些可能是通过 `async def` 声明,也可能是通过 `def` 声明。它们仍然可以正常工作,这些通过 `def` 声明的函数将会在外部线程中调用(来自线程池),而不是"被等待"。 +你可以拥有多个相互依赖的依赖以及[子依赖](tutorial/dependencies/sub-dependencies.md) (作为函数的参数),它们中的一些可能是通过 `async def` 声明,也可能是通过 `def` 声明。它们仍然可以正常工作,这些通过 `def` 声明的函数将会在外部线程中调用(来自线程池),而不是"被等待"。 ### 其他函数 { #other-utility-functions } diff --git a/docs/zh/docs/benchmarks.md b/docs/zh/docs/benchmarks.md index a6e706dfaa..d98d3de593 100644 --- a/docs/zh/docs/benchmarks.md +++ b/docs/zh/docs/benchmarks.md @@ -1,6 +1,6 @@ # 基准测试 { #benchmarks } -第三方机构 TechEmpower 的基准测试表明在 Uvicorn 下运行的 **FastAPI** 应用程序是 可用的最快的 Python 框架之一,仅次于 Starlette 和 Uvicorn 本身(由 FastAPI 内部使用)。 +第三方机构 TechEmpower 的基准测试表明在 Uvicorn 下运行的 **FastAPI** 应用程序是 [可用的最快的 Python 框架之一](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7),仅次于 Starlette 和 Uvicorn 本身(由 FastAPI 内部使用)。 但是在查看基准得分和对比时,请注意以下几点。 diff --git a/docs/zh/docs/deployment/cloud.md b/docs/zh/docs/deployment/cloud.md index 96883bd6bf..025715f523 100644 --- a/docs/zh/docs/deployment/cloud.md +++ b/docs/zh/docs/deployment/cloud.md @@ -6,7 +6,7 @@ ## FastAPI Cloud { #fastapi-cloud } -**FastAPI Cloud** 由 **FastAPI** 背后的同一作者与团队打造。 +**[FastAPI Cloud](https://fastapicloud.com)** 由 **FastAPI** 背后的同一作者与团队打造。 它简化了**构建**、**部署**和**访问** API 的流程,几乎不费力。 @@ -16,9 +16,9 @@ FastAPI Cloud 是 *FastAPI and friends* 开源项目的主要赞助方和资金 ## 云服务商 - 赞助商 { #cloud-providers-sponsors } -还有一些云服务商也会 ✨ [**赞助 FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨。🙇 +还有一些云服务商也会 ✨ [**赞助 FastAPI**](../help-fastapi.md#sponsor-the-author) ✨。🙇 你也可以考虑按照他们的指南尝试他们的服务: -* Render -* Railway +* [Render](https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi) +* [Railway](https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi) diff --git a/docs/zh/docs/deployment/concepts.md b/docs/zh/docs/deployment/concepts.md index 76e967d7de..dd5ba2ba80 100644 --- a/docs/zh/docs/deployment/concepts.md +++ b/docs/zh/docs/deployment/concepts.md @@ -25,7 +25,7 @@ ## 安全性 - HTTPS { #security-https } -在[上一章有关 HTTPS](https.md){.internal-link target=_blank} 中,我们了解了 HTTPS 如何为您的 API 提供加密。 +在[上一章有关 HTTPS](https.md) 中,我们了解了 HTTPS 如何为您的 API 提供加密。 我们还看到,HTTPS 通常由应用程序服务器的**外部**组件(**TLS 终止代理**)提供。 @@ -149,7 +149,7 @@ ### 崩溃后重新启动 { #restart-after-crash } -但在那些严重错误导致正在运行的**进程**崩溃的情况下,您需要一个外部组件来负责**重新启动**进程,至少尝试几次...... +但在那些严重错误导致正在运行的**进程**崩溃的情况下,您需要一个外部组件来负责**重新启动**进程,至少尝试几次... /// tip | 提示 @@ -190,7 +190,7 @@ ### 工作进程和端口 { #worker-processes-and-ports } -还记得文档 [关于 HTTPS](https.md){.internal-link target=_blank} 中只有一个进程可以侦听服务器中的端口和 IP 地址的一种组合吗? +还记得文档 [关于 HTTPS](https.md) 中只有一个进程可以侦听服务器中的端口和 IP 地址的一种组合吗? 现在仍然是对的。 @@ -243,7 +243,7 @@ 如果这些关于 **容器**、Docker 或 Kubernetes 的内容还没有多大意义,请不要担心。 -我将在以后的章节中向您详细介绍容器镜像、Docker、Kubernetes 等:[容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank}。 +我将在以后的章节中向您详细介绍容器镜像、Docker、Kubernetes 等:[容器中的 FastAPI - Docker](docker.md)。 /// @@ -281,7 +281,7 @@ /// tip | 提示 -我将在以后的章节中为您提供使用容器执行此操作的更具体示例:[容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank}。 +我将在以后的章节中为您提供使用容器执行此操作的更具体示例:[容器中的 FastAPI - Docker](docker.md)。 /// diff --git a/docs/zh/docs/deployment/docker.md b/docs/zh/docs/deployment/docker.md index 4e7410587e..aa7b60b508 100644 --- a/docs/zh/docs/deployment/docker.md +++ b/docs/zh/docs/deployment/docker.md @@ -1,6 +1,6 @@ # 容器中的 FastAPI - Docker { #fastapi-in-containers-docker } -部署 FastAPI 应用时,常见做法是构建一个**Linux 容器镜像**。通常使用 **Docker** 实现。然后你可以用几种方式之一部署该镜像。 +部署 FastAPI 应用时,常见做法是构建一个**Linux 容器镜像**。通常使用 [**Docker**](https://www.docker.com/) 实现。然后你可以用几种方式之一部署该镜像。 使用 Linux 容器有多种优势,包括**安全性**、**可复制性**、**简单性**等。 @@ -26,7 +26,7 @@ COPY ./app /code/app CMD ["fastapi", "run", "app/main.py", "--port", "80"] -# If running behind a proxy like Nginx or Traefik add --proxy-headers +# 如果在 Nginx 或 Traefik 等代理后运行,请添加 --proxy-headers # CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] ``` @@ -60,16 +60,16 @@ Linux 容器复用宿主机(物理机、虚拟机、云服务器等)的同 Docker 一直是创建和管理**容器镜像**与**容器**的主要工具之一。 -还有一个公共的 Docker Hub,其中为许多工具、环境、数据库和应用提供了预制的**官方容器镜像**。 +还有一个公共的 [Docker Hub](https://hub.docker.com/),其中为许多工具、环境、数据库和应用提供了预制的**官方容器镜像**。 -例如,有官方的 Python 镜像。 +例如,有官方的 [Python 镜像](https://hub.docker.com/_/python)。 还有许多用于不同目的(如数据库)的镜像,例如: -* PostgreSQL -* MySQL -* MongoDB -* Redis 等。 +* [PostgreSQL](https://hub.docker.com/_/postgres) +* [MySQL](https://hub.docker.com/_/mysql) +* [MongoDB](https://hub.docker.com/_/mongo) +* [Redis](https://hub.docker.com/_/redis) 等。 通过使用预制的容器镜像,可以很容易地**组合**并使用不同工具。例如,试用一个新的数据库。在大多数情况下,你可以直接使用**官方镜像**,只需通过环境变量配置即可。 @@ -111,7 +111,7 @@ Docker 一直是创建和管理**容器镜像**与**容器**的主要工具之 最常见的方式是使用 `requirements.txt` 文件,每行一个包名及其版本范围。 -当然,你也可以参考你在[关于 FastAPI 版本](versions.md){.internal-link target=_blank}中读到的思路来设置版本范围。 +当然,你也可以参考你在[关于 FastAPI 版本](versions.md)中读到的思路来设置版本范围。 例如,你的 `requirements.txt` 可能是: @@ -238,7 +238,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] #### 使用 `CMD` - Exec 形式 { #use-cmd-exec-form } -`CMD` 指令有两种写法: +[`CMD`](https://docs.docker.com/reference/dockerfile/#cmd) 指令有两种写法: ✅ **Exec** 形式: @@ -254,11 +254,11 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] CMD fastapi run app/main.py --port 80 ``` -务必使用**exec** 形式,以确保 FastAPI 可以优雅停机并触发[生命周期事件](../advanced/events.md){.internal-link target=_blank}。 +务必使用**exec** 形式,以确保 FastAPI 可以优雅停机并触发[生命周期事件](../advanced/events.md)。 -你可以在 Docker 文档(Shell 与 Exec 形式)中了解更多。 +你可以在 [Docker 文档(Shell 与 Exec 形式)](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form)中了解更多。 -在使用 `docker compose` 时这一点尤为明显。更多技术细节参见该 FAQ:为什么我的服务需要 10 秒才能重新创建或停止? +在使用 `docker compose` 时这一点尤为明显。更多技术细节参见该 FAQ:[为什么我的服务需要 10 秒才能重新创建或停止?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop) #### 目录结构 { #directory-structure } @@ -352,7 +352,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage ## 检查一下 { #check-it } -你应该能在容器暴露的 URL 访问它,例如:http://192.168.99.100/items/5?q=somequeryhttp://127.0.0.1/items/5?q=somequery(或其他等价地址,取决于你的 Docker 主机)。 +你应该能在容器暴露的 URL 访问它,例如:[http://192.168.99.100/items/5?q=somequery](http://192.168.99.100/items/5?q=somequery) 或 [http://127.0.0.1/items/5?q=somequery](http://127.0.0.1/items/5?q=somequery)(或其他等价地址,取决于你的 Docker 主机)。 你会看到类似内容: @@ -362,17 +362,17 @@ $ docker run -d --name mycontainer -p 80:80 myimage ## 交互式 API 文档 { #interactive-api-docs } -现在你可以访问 http://192.168.99.100/docshttp://127.0.0.1/docs(或其他等价地址,取决于你的 Docker 主机)。 +现在你可以访问 [http://192.168.99.100/docs](http://192.168.99.100/docs) 或 [http://127.0.0.1/docs](http://127.0.0.1/docs)(或其他等价地址,取决于你的 Docker 主机)。 -你将看到自动生成的交互式 API 文档(由 Swagger UI 提供): +你将看到自动生成的交互式 API 文档(由 [Swagger UI](https://github.com/swagger-api/swagger-ui) 提供): ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) ## 备选 API 文档 { #alternative-api-docs } -你还可以访问 http://192.168.99.100/redochttp://127.0.0.1/redoc(或其他等价地址,取决于你的 Docker 主机)。 +你还可以访问 [http://192.168.99.100/redoc](http://192.168.99.100/redoc) 或 [http://127.0.0.1/redoc](http://127.0.0.1/redoc)(或其他等价地址,取决于你的 Docker 主机)。 -你将看到备选的自动文档(由 ReDoc 提供): +你将看到备选的自动文档(由 [ReDoc](https://github.com/Rebilly/ReDoc) 提供): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -413,7 +413,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] ## 部署概念 { #deployment-concepts } -我们再从容器的角度讨论一些相同的[部署概念](concepts.md){.internal-link target=_blank}。 +我们再从容器的角度讨论一些相同的[部署概念](concepts.md)。 容器主要是简化应用**构建与部署**流程的工具,但它们并不强制采用某种特定方式来处理这些**部署概念**,可选策略有多种。 @@ -432,7 +432,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] 如果我们只关注 FastAPI 应用的**容器镜像**(以及后续运行的**容器**),HTTPS 通常由**外部**的其他工具处理。 -它可以是另一个容器,例如使用 Traefik,处理 **HTTPS** 并**自动**获取**证书**。 +它可以是另一个容器,例如使用 [Traefik](https://traefik.io/),处理 **HTTPS** 并**自动**获取**证书**。 /// tip | 提示 @@ -558,7 +558,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] /// info | 信息 -如果你使用 Kubernetes,这通常会是一个 Init Container。 +如果你使用 Kubernetes,这通常会是一个 [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)。 /// @@ -570,7 +570,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] ### 基础 Docker 镜像 { #base-docker-image } -曾经有一个官方的 FastAPI Docker 镜像:tiangolo/uvicorn-gunicorn-fastapi。但它现在已被弃用。⛔️ +曾经有一个官方的 FastAPI Docker 镜像:[tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker)。但它现在已被弃用。⛔️ 你大概率**不应该**使用这个基础镜像(或任何其它类似的镜像)。 @@ -600,7 +600,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] ## 使用 `uv` 的 Docker 镜像 { #docker-image-with-uv } -如果你使用 uv 来安装和管理项目,可以参考他们的 uv Docker 指南。 +如果你使用 [uv](https://github.com/astral-sh/uv) 来安装和管理项目,可以参考他们的 [uv Docker 指南](https://docs.astral.sh/uv/guides/integration/docker/)。 ## 回顾 { #recap } diff --git a/docs/zh/docs/deployment/fastapicloud.md b/docs/zh/docs/deployment/fastapicloud.md index 0239a15128..d438709935 100644 --- a/docs/zh/docs/deployment/fastapicloud.md +++ b/docs/zh/docs/deployment/fastapicloud.md @@ -1,6 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -你可以用**一条命令**将你的 FastAPI 应用部署到 FastAPI Cloud,如果还没有,去加入候补名单吧。🚀 +你可以用**一条命令**将你的 FastAPI 应用部署到 [FastAPI Cloud](https://fastapicloud.com),如果还没有,去加入候补名单吧。🚀 ## 登录 { #login } @@ -40,7 +40,7 @@ Deploying to FastAPI Cloud... ## 关于 FastAPI Cloud { #about-fastapi-cloud } -**FastAPI Cloud** 由 **FastAPI** 背后的作者与团队打造。 +**[FastAPI Cloud](https://fastapicloud.com)** 由 **FastAPI** 背后的作者与团队打造。 它让你以最小的投入完成 API 的**构建**、**部署**与**访问**。 diff --git a/docs/zh/docs/deployment/https.md b/docs/zh/docs/deployment/https.md index 591707f6dd..916fb46da2 100644 --- a/docs/zh/docs/deployment/https.md +++ b/docs/zh/docs/deployment/https.md @@ -10,7 +10,7 @@ /// -要从用户的视角**了解 HTTPS 的基础知识**,请查看 https://howhttps.works/。 +要从用户的视角**了解 HTTPS 的基础知识**,请查看 [https://howhttps.works/](https://howhttps.works/)。 现在,从**开发人员的视角**,在了解 HTTPS 时需要记住以下几点: @@ -28,13 +28,13 @@ * **默认情况下**,这意味着你**每个 IP 地址只能拥有一个 HTTPS 证书**。 * 无论你的服务器有多大,或者服务器上的每个应用程序有多小。 * 不过,对此有一个**解决方案**。 -* **TLS** 协议(在 HTTP 之下的 TCP 层处理加密的协议)有一个**扩展**,称为 **SNI**。 +* **TLS** 协议(在 HTTP 之下的 TCP 层处理加密的协议)有一个**扩展**,称为 **[SNI](https://en.wikipedia.org/wiki/Server_Name_Indication)**。 * SNI 扩展允许一台服务器(具有 **单个 IP 地址**)拥有 **多个 HTTPS 证书** 并提供 **多个 HTTPS 域名/应用程序**。 * 为此,服务器上会有**单独**的一个组件(程序)侦听**公共 IP 地址**,这个组件必须拥有服务器中的**所有 HTTPS 证书**。 * **获得安全连接后**,通信协议**仍然是HTTP**。 * 内容是 **加密过的**,即使它们是通过 **HTTP 协议** 发送的。 -通常的做法是在服务器上运行**一个程序/HTTP 服务器**并**管理所有 HTTPS 部分**:接收**加密的 HTTPS 请求**, 将 **解密的 HTTP 请求** 发送到在同一服务器中运行的实际 HTTP 应用程序(在本例中为 **FastAPI** 应用程序),从应用程序中获取 **HTTP 响应**, 使用适当的 **HTTPS 证书**对其进行加密并使用 **HTTPS** 将其发送回客户端。 此服务器通常被称为 **TLS 终止代理(TLS Termination Proxy)**。 +通常的做法是在服务器上运行**一个程序/HTTP 服务器**并**管理所有 HTTPS 部分**:接收**加密的 HTTPS 请求**, 将 **解密的 HTTP 请求** 发送到在同一服务器中运行的实际 HTTP 应用程序(在本例中为 **FastAPI** 应用程序),从应用程序中获取 **HTTP 响应**, 使用适当的 **HTTPS 证书**对其进行加密并使用 **HTTPS** 将其发送回客户端。 此服务器通常被称为 **[TLS 终止代理(TLS Termination Proxy)](https://en.wikipedia.org/wiki/TLS_termination_proxy)**。 你可以用作 TLS 终止代理的一些选项包括: @@ -49,7 +49,7 @@ 过去,获得这些证书的过程非常繁琐,需要大量的文书工作,而且证书非常昂贵。 -但随后 **Let's Encrypt** 创建了。 +但随后 **[Let's Encrypt](https://letsencrypt.org/)** 创建了。 它是 Linux 基金会的一个项目。 它以自动方式免费提供 **HTTPS 证书**。 这些证书可以使用所有符合标准的安全加密,并且有效期很短(大约 3 个月),因此**安全性实际上更好**,因为它们的生命周期缩短了。 @@ -201,9 +201,9 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**( 这些代理请求头包括: -* X-Forwarded-For -* X-Forwarded-Proto -* X-Forwarded-Host +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) /// @@ -219,7 +219,7 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**( /// tip | 提示 -你可以在文档中了解更多:[在代理之后 - 启用代理转发请求头](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} +你可以在文档中了解更多:[在代理之后 - 启用代理转发请求头](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) /// diff --git a/docs/zh/docs/deployment/index.md b/docs/zh/docs/deployment/index.md index 47dcede653..fa10019adf 100644 --- a/docs/zh/docs/deployment/index.md +++ b/docs/zh/docs/deployment/index.md @@ -16,7 +16,7 @@ 你可以使用一些工具自行**部署服务器**,你也可以使用能为你完成部分工作的**云服务**,或其他可能的选项。 -例如,我们(FastAPI 团队)构建了 **FastAPI Cloud**,让将 FastAPI 应用部署到云端尽可能流畅,并且保持与使用 FastAPI 开发时相同的开发者体验。 +例如,我们(FastAPI 团队)构建了 [**FastAPI Cloud**](https://fastapicloud.com),让将 FastAPI 应用部署到云端尽可能流畅,并且保持与使用 FastAPI 开发时相同的开发者体验。 我将向你展示在部署 **FastAPI** 应用程序时你可能应该记住的一些主要概念(尽管其中大部分适用于任何其他类型的 Web 应用程序)。 diff --git a/docs/zh/docs/deployment/manually.md b/docs/zh/docs/deployment/manually.md index f519c1e87a..c440aa924b 100644 --- a/docs/zh/docs/deployment/manually.md +++ b/docs/zh/docs/deployment/manually.md @@ -52,11 +52,11 @@ FastAPI 使用了一种用于构建 Python Web 框架和服务器的标准,称 除此之外,还有其他一些可选的 ASGI 服务器,例如: -* Uvicorn:高性能 ASGI 服务器。 -* Hypercorn:与 HTTP/2 和 Trio 等兼容的 ASGI 服务器。 -* Daphne:为 Django Channels 构建的 ASGI 服务器。 -* Granian:基于 Rust 的 HTTP 服务器,专为 Python 应用设计。 -* NGINX Unit:NGINX Unit 是一个轻量级且灵活的 Web 应用运行时环境。 +* [Uvicorn](https://www.uvicorn.dev/): 高性能 ASGI 服务器。 +* [Hypercorn](https://hypercorn.readthedocs.io/): 与 HTTP/2 和 Trio 等兼容的 ASGI 服务器。 +* [Daphne](https://github.com/django/daphne): 为 Django Channels 构建的 ASGI 服务器。 +* [Granian](https://github.com/emmett-framework/granian): 基于 Rust 的 HTTP 服务器,专为 Python 应用设计。 +* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): NGINX Unit 是一个轻量级且灵活的 Web 应用运行时环境。 ## 服务器主机和服务器程序 { #server-machine-and-server-program } @@ -74,7 +74,7 @@ FastAPI 使用了一种用于构建 Python Web 框架和服务器的标准,称 不过,您也可以手动安装 ASGI 服务器。 -请确保您创建并激活一个[虚拟环境](../virtual-environments.md){.internal-link target=_blank},然后再安装服务器应用程序。 +请确保您创建并激活一个[虚拟环境](../virtual-environments.md),然后再安装服务器应用程序。 例如,要安装 Uvicorn,可以运行以下命令: diff --git a/docs/zh/docs/deployment/server-workers.md b/docs/zh/docs/deployment/server-workers.md index 2bbd5d9b6a..add83ac1af 100644 --- a/docs/zh/docs/deployment/server-workers.md +++ b/docs/zh/docs/deployment/server-workers.md @@ -13,13 +13,13 @@ 部署应用程序时,您可能希望进行一些**进程复制**,以利用**多核** CPU 并能够处理更多请求。 -正如您在上一章有关[部署概念](concepts.md){.internal-link target=_blank}中看到的,您可以使用多种策略。 +正如您在上一章有关[部署概念](concepts.md)中看到的,您可以使用多种策略。 在本章节中,我将向您展示如何使用 `fastapi` 命令或直接使用 `uvicorn` 命令以**多工作进程模式**运行 **Uvicorn**。 /// info | 信息 -如果您正在使用容器,例如 Docker 或 Kubernetes,我将在下一章中告诉您更多相关信息:[容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank}。 +如果您正在使用容器,例如 Docker 或 Kubernetes,我将在下一章中告诉您更多相关信息:[容器中的 FastAPI - Docker](docker.md)。 比较特别的是,在 **Kubernetes** 环境中运行时,您通常**不需要**使用多个工作进程,而是**每个容器运行一个 Uvicorn 进程**。不过,我会在本章节的后续部分详细介绍这一点。 @@ -126,7 +126,7 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 ## 容器和 Docker { #containers-and-docker } -在关于 [容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank} 的下一章中,我将介绍一些可用于处理其他**部署概念**的策略。 +在关于 [容器中的 FastAPI - Docker](docker.md) 的下一章中,我将介绍一些可用于处理其他**部署概念**的策略。 我将向您展示如何**从零开始构建自己的镜像**,以运行一个单独的 Uvicorn 进程。这个过程相对简单,并且在使用 **Kubernetes** 等分布式容器管理系统时,这通常是您需要采取的方法。 diff --git a/docs/zh/docs/deployment/versions.md b/docs/zh/docs/deployment/versions.md index 23c37f3b5b..13af705568 100644 --- a/docs/zh/docs/deployment/versions.md +++ b/docs/zh/docs/deployment/versions.md @@ -4,7 +4,7 @@ 经常添加新功能,定期修复错误,并且代码仍在持续改进。 -这就是为什么当前版本仍然是`0.x.x`,这反映出每个版本都可能有Breaking changes。 这遵循语义版本控制的约定。 +这就是为什么当前版本仍然是`0.x.x`,这反映出每个版本都可能有Breaking changes。 这遵循[语义版本控制](https://semver.org/)的约定。 你现在就可以使用 **FastAPI** 创建生产环境应用程序(你可能已经这样做了一段时间),你只需确保使用的版本可以与其余代码正确配合即可。 @@ -34,7 +34,7 @@ fastapi[standard]>=0.112.0,<0.113.0 ## 可用版本 { #available-versions } -你可以在[发行说明](../release-notes.md){.internal-link target=_blank}中查看可用版本(例如查看当前最新版本)。 +你可以在[发行说明](../release-notes.md)中查看可用版本(例如查看当前最新版本)。 ## 关于版本 { #about-versions } @@ -66,7 +66,7 @@ fastapi>=0.45.0,<0.46.0 你应该为你的应用程序添加测试。 -使用 **FastAPI** 编写测试非常简单(感谢 Starlette),请参考文档:[测试](../tutorial/testing.md){.internal-link target=_blank} +使用 **FastAPI** 编写测试非常简单(感谢 Starlette),请参考文档:[测试](../tutorial/testing.md) 添加测试后,你可以将 **FastAPI** 版本升级到更新版本,并通过运行测试来确保所有代码都能正常工作。 diff --git a/docs/zh/docs/environment-variables.md b/docs/zh/docs/environment-variables.md index 8729a6306a..3a90ecde62 100644 --- a/docs/zh/docs/environment-variables.md +++ b/docs/zh/docs/environment-variables.md @@ -65,7 +65,7 @@ print(f"Hello {name} from Python") /// tip | 提示 -第二个参数是 `os.getenv()` 的默认返回值。 +第二个参数是 [`os.getenv()`](https://docs.python.org/3.8/library/os.html#os.getenv) 的默认返回值。 如果没有提供,默认值为 `None`,这里我们提供 `"World"` 作为默认值。 @@ -153,7 +153,7 @@ Hello World from Python /// tip | 提示 -你可以在 The Twelve-Factor App: 配置中了解更多信息。 +你可以在 [The Twelve-Factor App: 配置](https://12factor.net/config) 中了解更多信息。 /// @@ -163,7 +163,7 @@ Hello World from Python 这意味着从环境变量中读取的**任何值**在 Python 中都将是一个 `str`,任何类型转换或验证都必须在代码中完成。 -你将在[高级用户指南 - 设置和环境变量](./advanced/settings.md){.internal-link target=_blank}中了解更多关于使用环境变量处理**应用程序设置**的信息。 +你将在[高级用户指南 - 设置和环境变量](./advanced/settings.md)中了解更多关于使用环境变量处理**应用程序设置**的信息。 ## `PATH` 环境变量 { #path-environment-variable } @@ -285,13 +285,13 @@ $ C:\opt\custompython\bin\python //// -当学习[虚拟环境](virtual-environments.md){.internal-link target=_blank}时,这些信息将会很有用。 +当学习[虚拟环境](virtual-environments.md)时,这些信息将会很有用。 ## 结论 { #conclusion } 通过这个教程,你应该对**环境变量**是什么以及如何在 Python 中使用它们有了基本的了解。 -你也可以在环境变量 - 维基百科中了解更多关于它们的信息。 +你也可以在[环境变量 - 维基百科](https://en.wikipedia.org/wiki/Environment_variable)中了解更多关于它们的信息。 在许多情况下,环境变量的用途和适用性并不是很明显。但是在开发过程中,它们会在许多不同的场景中出现,因此了解它们是很有必要的。 diff --git a/docs/zh/docs/fastapi-cli.md b/docs/zh/docs/fastapi-cli.md index 4d3b51a57a..151b7e61ec 100644 --- a/docs/zh/docs/fastapi-cli.md +++ b/docs/zh/docs/fastapi-cli.md @@ -1,15 +1,15 @@ # FastAPI CLI { #fastapi-cli } -**FastAPI CLI** 是一个命令行程序,你可以用它来部署和运行你的 FastAPI 应用程序,管理你的 FastAPI 项目,等等。 +**FastAPI CLI** 是一个命令行程序,你可以用它来部署和运行你的 FastAPI 应用、管理 FastAPI 项目,等等。 -当你安装 FastAPI 时(例如使用 `pip install "fastapi[standard]"`),会包含一个名为 `fastapi-cli` 的软件包,该软件包在终端中提供 `fastapi` 命令。 +当你安装 FastAPI(例如使用 `pip install "fastapi[standard]"`)时,会附带一个可以在终端中运行的命令行程序。 -要在开发环境中运行你的 FastAPI 应用,你可以使用 `fastapi dev` 命令: +要在开发环境中运行你的 FastAPI 应用,可以使用 `fastapi dev` 命令:
```console -$ fastapi dev main.py +$ fastapi dev FastAPI Starting development server 🚀 @@ -46,13 +46,66 @@ $ fastapi dev Uvicorn,这是一个高性能、适用于生产环境的 ASGI 服务器。😎 +另外,其他工具可能找不到它,例如 [VS Code 扩展](editor-support.md) 或 [FastAPI Cloud](https://fastapicloud.com),因此推荐在 `pyproject.toml` 中使用 `entrypoint`。 ## `fastapi dev` { #fastapi-dev } @@ -70,6 +123,6 @@ FastAPI CLI 接收你的 Python 程序路径(例如 `main.py`),自动检 /// tip | 提示 -你可以在[部署文档](deployment/index.md){.internal-link target=_blank}中了解更多。 +你可以在[部署文档](deployment/index.md)中了解更多。 /// diff --git a/docs/zh/docs/features.md b/docs/zh/docs/features.md index 1414f7c6fc..ad6b77f74f 100644 --- a/docs/zh/docs/features.md +++ b/docs/zh/docs/features.md @@ -6,8 +6,8 @@ ### 基于开放标准 { #based-on-open-standards } -* 用于创建 API 的 OpenAPI,包含对路径 操作、参数、请求体、安全等的声明。 -* 使用 JSON Schema 自动生成数据模型文档(因为 OpenAPI 本身就是基于 JSON Schema 的)。 +* [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) 用于创建 API,包含对路径 操作、参数、请求体、安全等的声明。 +* 使用 [**JSON Schema**](https://json-schema.org/) 自动生成数据模型文档(因为 OpenAPI 本身就是基于 JSON Schema 的)。 * 经过了缜密的研究后围绕这些标准而设计。并非狗尾续貂。 * 这也允许了在很多语言中自动**生成客户端代码**。 @@ -15,11 +15,11 @@ 交互式 API 文档以及具探索性 web 界面。因为该框架是基于 OpenAPI,所以有很多可选项,FastAPI 默认自带两个交互式 API 文档。 -* Swagger UI,可交互式操作,能在浏览器中直接调用和测试你的 API。 +* [**Swagger UI**](https://github.com/swagger-api/swagger-ui),可交互式操作,能在浏览器中直接调用和测试你的 API。 ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* 另外的 API 文档:ReDoc +* 另外的 API 文档:[**ReDoc**](https://github.com/Rebilly/ReDoc) ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) @@ -27,7 +27,7 @@ 全部都基于标准的 **Python 类型** 声明(感谢 Pydantic)。没有新的语法需要学习。只需要标准的现代 Python。 -如果你需要2分钟来学习如何使用 Python 类型(即使你不使用 FastAPI),看看这个简短的教程:[Python Types](python-types.md){.internal-link target=_blank}。 +如果你需要2分钟来学习如何使用 Python 类型(即使你不使用 FastAPI),看看这个简短的教程:[Python 类型](python-types.md)。 编写带有类型标注的标准 Python: @@ -76,7 +76,7 @@ my_second_user: User = User(**second_user_data) 整个框架都被设计得易于使用且直观,所有的决定都在开发之前就在多个编辑器上进行了测试,来确保最佳的开发体验。 -在最近的 Python 开发者调查中,我们能看到 被使用最多的功能是“自动补全”。 +在 Python 开发者调查中,我们能看到[被使用最多的功能之一是“自动补全”](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features)。 整个 **FastAPI** 框架就是基于这一点的。任何地方都可以进行自动补全。 @@ -84,11 +84,11 @@ my_second_user: User = User(**second_user_data) 在这里,你的编辑器可能会这样帮助你: -* 在 Visual Studio Code 中: +* 在 [Visual Studio Code](https://code.visualstudio.com/) 中: ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -* 在 PyCharm 中: +* 在 [PyCharm](https://www.jetbrains.com/pycharm/) 中: ![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) @@ -125,7 +125,7 @@ my_second_user: User = User(**second_user_data) OpenAPI 中定义的安全模式,包括: * HTTP 基本认证。 -* **OAuth2**(也使用 **JWT tokens**)。在 [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}查看教程。 +* **OAuth2**(也使用 **JWT tokens**)。在 [使用 JWT 的 OAuth2](tutorial/security/oauth2-jwt.md) 查看教程。 * API 密钥,在: * 请求头。 * 查询参数。 @@ -142,7 +142,7 @@ FastAPI 有一个使用非常简单,但是非常强大的Starlette 完全兼容(并基于)。所以,你有的其他的 Starlette 代码也能正常工作。`FastAPI` 实际上是 `Starlette` 的一个子类。所以,如果你已经知道或者使用 Starlette,大部分的功能会以相同的方式工作。 +**FastAPI** 和 [**Starlette**](https://www.starlette.dev/) 完全兼容(并基于)。所以,你有的其他的 Starlette 代码也能正常工作。`FastAPI` 实际上是 `Starlette` 的一个子类。所以,如果你已经知道或者使用 Starlette,大部分的功能会以相同的方式工作。 通过 **FastAPI** 你可以获得所有 **Starlette** 的特性(FastAPI 就像加强版的 Starlette): -* 令人惊叹的性能。它是 Python 可用的最快的框架之一,和 **NodeJS** 及 **Go** 相当。 +* 令人惊叹的性能。它是[Python 可用的最快的框架之一,和 **NodeJS** 及 **Go** 相当](https://github.com/encode/starlette#performance)。 * **支持 WebSocket**。 * 进程内后台任务。 * Startup 和 shutdown 事件。 @@ -176,7 +176,7 @@ FastAPI 有一个使用非常简单,但是非常强大的发推谈谈 **FastAPI**,告诉我和大家你为什么喜欢它。🎉 +[发推谈谈 **FastAPI**](https://x.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi),告诉我和大家你为什么喜欢它。🎉 我很高兴听到 **FastAPI** 的使用情况、你喜欢它的哪些点、你在哪个项目/公司使用它,等等。 ## 为 FastAPI 投票 { #vote-for-fastapi } -* 在 Slant 上为 **FastAPI** 投票。 -* 在 AlternativeTo 上为 **FastAPI** 投票。 -* 在 StackShare 上标注你在用 **FastAPI**。 +* [在 Slant 上为 **FastAPI** 投票](https://www.slant.co/options/34241/~fastapi-review)。 +* [在 AlternativeTo 上为 **FastAPI** 投票](https://alternativeto.net/software/fastapi/about/)。 +* [在 StackShare 上标注你在用 **FastAPI**](https://stackshare.io/pypi-fastapi)。 ## 在 GitHub 上帮别人解答问题 { #help-others-with-questions-in-github } 你可以尝试在以下地方帮助他人解答问题: -* GitHub Discussions -* GitHub Issues +* [GitHub Discussions](https://github.com/fastapi/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered) +* [GitHub Issues](https://github.com/fastapi/fastapi/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Aquestion+-label%3Aanswered+) 很多情况下,你也许已经知道这些问题的答案了。🤓 -如果你帮助了很多人解答问题,你会成为官方的 [FastAPI 专家](fastapi-people.md#fastapi-experts){.internal-link target=_blank}。🎉 +如果你帮助了很多人解答问题,你会成为官方的 [FastAPI 专家](fastapi-people.md#fastapi-experts)。🎉 只要记住,最重要的一点是:尽量友善。人们带着挫败感而来,很多时候他们的提问方式并不理想,但请尽你所能地友好对待。🤗 @@ -104,7 +104,7 @@ 很多时候他们只会粘贴一小段代码,但这不足以**复现问题**。 -* 你可以请他们提供一个可最小复现的示例,你可以**复制粘贴**并在本地运行,看到与他们相同的错误或行为,或者更好地理解他们的用例。 +* 你可以请他们提供一个[可最小复现的示例](https://stackoverflow.com/help/minimal-reproducible-example),你可以**复制粘贴**并在本地运行,看到与他们相同的错误或行为,或者更好地理解他们的用例。 * 如果你非常热心,你也可以尝试仅根据问题描述自己**构造一个示例**。不过要记住,这可能会花很多时间,通常先请他们澄清问题会更好。 @@ -124,7 +124,7 @@ ## 关注 GitHub 资源库 { #watch-the-github-repository } -你可以在 GitHub 上「关注」FastAPI(点击右上角的「watch」按钮):https://github.com/fastapi/fastapi。👀 +你可以在 GitHub 上「关注」FastAPI(点击右上角的「watch」按钮):[https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi)。👀 如果你选择「Watching」而非「Releases only」,当有人创建新的 issue 或问题时你会收到通知。你也可以指定只通知新 issues、discussions、PR 等。 @@ -132,7 +132,7 @@ ## 提问 { #ask-questions } -你可以在 GitHub 资源库中创建一个新问题(Question),例如: +你可以在 GitHub 资源库中[创建一个新问题(Question)](https://github.com/fastapi/fastapi/discussions/new?category=questions),例如: * 提出一个**问题**或关于某个**问题**的求助。 * 建议一个新的**功能**。 @@ -195,12 +195,12 @@ ## 创建 Pull Request { #create-a-pull-request } -你可以通过 Pull Request 为源代码[做贡献](contributing.md){.internal-link target=_blank},例如: +你可以通过 Pull Request 为源代码[做贡献](contributing.md),例如: * 修正文档中的一个错别字。 -* 通过编辑这个文件分享你创建或发现的关于 FastAPI 的文章、视频或播客。 +* 通过[编辑这个文件](https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml)分享你创建或发现的关于 FastAPI 的文章、视频或播客。 * 请确保把你的链接添加到相应区块的开头。 -* 帮助把[文档翻译](contributing.md#translations){.internal-link target=_blank}成你的语言。 +* 帮助把[文档翻译](contributing.md#translations)成你的语言。 * 你也可以审阅他人创建的翻译。 * 提议新增文档章节。 * 修复现有 issue/bug。 @@ -217,8 +217,8 @@ 你现在就能做的主要事情有: -* [在 GitHub 上帮别人解答问题](#help-others-with-questions-in-github){.internal-link target=_blank}(见上面的章节)。 -* [审阅 Pull Request](#review-pull-requests){.internal-link target=_blank}(见上面的章节)。 +* [在 GitHub 上帮别人解答问题](#help-others-with-questions-in-github)(见上面的章节)。 +* [审阅 Pull Request](#review-pull-requests)(见上面的章节)。 这两项工作是**最耗时**的。这也是维护 FastAPI 的主要工作。 @@ -226,11 +226,11 @@ ## 加入聊天 { #join-the-chat } -加入 👥 Discord 聊天服务器 👥,和 FastAPI 社区的小伙伴们一起交流。 +加入 👥 [Discord 聊天服务器](https://discord.gg/VQjSZaeJmf) 👥,和 FastAPI 社区的小伙伴们一起交流。 /// tip | 提示 -关于提问,请在 GitHub Discussions 中发布,这样更有机会得到 [FastAPI 专家](fastapi-people.md#fastapi-experts){.internal-link target=_blank} 的帮助。 +关于提问,请在 [GitHub Discussions](https://github.com/fastapi/fastapi/discussions/new?category=questions) 中发布,这样更有机会得到 [FastAPI 专家](fastapi-people.md#fastapi-experts) 的帮助。 聊天仅用于其他日常交流。 @@ -242,13 +242,13 @@ 在 GitHub 中,模板会引导你写出恰当的问题,从而更容易获得好的回答,甚至在提问之前就能自己解决。而且在 GitHub 里,我能尽量确保最终回复每个问题,即使这需要一些时间。对聊天系统来说,我个人做不到这一点。😅 -聊天系统中的对话也不像 GitHub 那样容易搜索,因此问答可能在聊天中淹没。而且只有在 GitHub 中的问答才会计入成为 [FastAPI 专家](fastapi-people.md#fastapi-experts){.internal-link target=_blank} 的贡献,所以你在 GitHub 上更可能获得关注。 +聊天系统中的对话也不像 GitHub 那样容易搜索,因此问答可能在聊天中淹没。而且只有在 GitHub 中的问答才会计入成为 [FastAPI 专家](fastapi-people.md#fastapi-experts) 的贡献,所以你在 GitHub 上更可能获得关注。 另一方面,聊天系统里有成千上万的用户,你几乎随时都能在那里找到聊得来的人。😄 ## 赞助作者 { #sponsor-the-author } -如果你的**产品/公司**依赖或与 **FastAPI** 相关,并且你想触达它的用户,你可以通过 GitHub sponsors 赞助作者(我)。根据赞助层级,你还可能获得一些额外福利,比如在文档中展示徽章。🎁 +如果你的**产品/公司**依赖或与 **FastAPI** 相关,并且你想触达它的用户,你可以通过 [GitHub sponsors](https://github.com/sponsors/tiangolo) 赞助作者(我)。根据赞助层级,你还可能获得一些额外福利,比如在文档中展示徽章。🎁 --- diff --git a/docs/zh/docs/history-design-future.md b/docs/zh/docs/history-design-future.md index 00945eab59..429eb8db0d 100644 --- a/docs/zh/docs/history-design-future.md +++ b/docs/zh/docs/history-design-future.md @@ -1,6 +1,6 @@ # 历史、设计、未来 { #history-design-and-future } -不久前,曾有 **FastAPI** 用户问过: +不久前,[曾有 **FastAPI** 用户问过](https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920): > 这个项目有怎样的历史?好像它只用了几周就从默默无闻变得众所周知... @@ -14,7 +14,7 @@ **FastAPI** 其实只是延续了这些前辈的历史。 -正如[备选方案](alternatives.md){.internal-link target=_blank}一章所述: +正如[备选方案](alternatives.md)一章所述:
没有大家之前所做的工作,**FastAPI** 就不会存在。 @@ -42,7 +42,7 @@ 同时,我还在最流行的 Python 代码编辑器中测试了很多思路,包括 PyCharm、VS Code、基于 Jedi 的编辑器。 -根据最新 Python 开发者调研报告显示,这几种编辑器覆盖了约 80% 的用户。 +根据最新 [Python 开发者调研报告](https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools)显示,这几种编辑器覆盖了约 80% 的用户。 也就是说,**FastAPI** 针对差不多 80% 的 Python 开发者使用的编辑器进行了测试,而且其它大多数编辑器的工作方式也与之类似,因此,**FastAPI** 的优势几乎能在所有编辑器上体现。 @@ -52,11 +52,11 @@ ## 需求项 { #requirements } -经过测试多种备选方案,我最终决定使用 **Pydantic**,并充分利用它的优势。 +经过测试多种备选方案,我最终决定使用 [**Pydantic**](https://docs.pydantic.dev/),并充分利用它的优势。 我甚至为它做了不少贡献,让它完美兼容了 JSON Schema,支持多种方式定义约束声明,并基于多个编辑器,改进了它对编辑器支持(类型检查、自动补全)。 -在开发期间,我还为 **Starlette** 做了不少贡献,这是另一个关键需求项。 +在开发期间,我还为 [**Starlette**](https://www.starlette.dev/) 做了不少贡献,这是另一个关键需求项。 ## 开发 { #development } @@ -74,4 +74,4 @@ **FastAPI** 前景光明。 -在此,我们衷心感谢[您的帮助](help-fastapi.md){.internal-link target=_blank}。 +在此,我们衷心感谢[你的帮助](help-fastapi.md)。 diff --git a/docs/zh/docs/how-to/authentication-error-status-code.md b/docs/zh/docs/how-to/authentication-error-status-code.md index 466b90e15a..6f8c0a67cd 100644 --- a/docs/zh/docs/how-to/authentication-error-status-code.md +++ b/docs/zh/docs/how-to/authentication-error-status-code.md @@ -2,7 +2,7 @@ 在 FastAPI `0.122.0` 版本之前,当内置的安全工具在认证失败后向客户端返回错误时,会使用 HTTP 状态码 `403 Forbidden`。 -从 FastAPI `0.122.0` 版本开始,它们改用更合适的 HTTP 状态码 `401 Unauthorized`,并在响应中返回合理的 `WWW-Authenticate` 头,遵循 HTTP 规范,RFC 7235RFC 9110。 +从 FastAPI `0.122.0` 版本开始,它们改用更合适的 HTTP 状态码 `401 Unauthorized`,并在响应中返回合理的 `WWW-Authenticate` 头,遵循 HTTP 规范,[RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-3.1)、[RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized)。 但如果由于某些原因你的客户端依赖旧行为,你可以在你的安全类中重写方法 `make_not_authenticated_error` 来回退到旧行为。 diff --git a/docs/zh/docs/how-to/conditional-openapi.md b/docs/zh/docs/how-to/conditional-openapi.md index d26b5f3bd0..b0c5d521c1 100644 --- a/docs/zh/docs/how-to/conditional-openapi.md +++ b/docs/zh/docs/how-to/conditional-openapi.md @@ -10,7 +10,7 @@ 如果你的代码里有安全漏洞,它仍然存在。 -隐藏文档只会让理解如何与 API 交互变得更困难,也可能让你在生产环境中调试更困难。这大体上可以被视为一种 通过隐藏实现安全 的做法。 +隐藏文档只会让理解如何与 API 交互变得更困难,也可能让你在生产环境中调试更困难。这大体上可以被视为一种 [通过隐藏实现安全](https://en.wikipedia.org/wiki/Security_through_obscurity) 的做法。 如果你想保护你的 API,有很多更好的措施,例如: diff --git a/docs/zh/docs/how-to/configure-swagger-ui.md b/docs/zh/docs/how-to/configure-swagger-ui.md index bf26246573..3dbc54911b 100644 --- a/docs/zh/docs/how-to/configure-swagger-ui.md +++ b/docs/zh/docs/how-to/configure-swagger-ui.md @@ -1,10 +1,10 @@ # 配置 Swagger UI { #configure-swagger-ui } -你可以配置一些额外的 Swagger UI 参数. +你可以配置一些额外的 [Swagger UI 参数](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/)。 如果需要配置它们,可以在创建 `FastAPI()` 应用对象时或调用 `get_swagger_ui_html()` 函数时传递 `swagger_ui_parameters` 参数。 -`swagger_ui_parameters` 接受一个直接传递给 Swagger UI的字典,包含配置参数键值对。 +`swagger_ui_parameters` 接受一个字典,该字典会直接传递给 Swagger UI。 FastAPI会将这些配置转换为 **JSON**,使其与 JavaScript 兼容,因为这是 Swagger UI 需要的。 @@ -50,7 +50,7 @@ FastAPI 包含了一些默认配置参数,适用于大多数用例。 ## 其他 Swagger UI 参数 { #other-swagger-ui-parameters } -查看所有其他可用的配置,请阅读 Swagger UI 参数文档。 +查看所有其他可用的配置,请阅读官方的 [Swagger UI 参数文档](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/)。 ## JavaScript-only 配置 { #javascript-only-settings } diff --git a/docs/zh/docs/how-to/custom-docs-ui-assets.md b/docs/zh/docs/how-to/custom-docs-ui-assets.md index 9e6e5a66b8..47b27b69ca 100644 --- a/docs/zh/docs/how-to/custom-docs-ui-assets.md +++ b/docs/zh/docs/how-to/custom-docs-ui-assets.md @@ -54,7 +54,7 @@ Swagger UI 会在幕后为你处理这些,但它需要这个“重定向”辅 ### 测试 { #test-it } -现在,你应该可以访问 http://127.0.0.1:8000/docs,并刷新页面,页面会从新的 CDN 加载这些资源。 +现在,你应该可以访问 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs),并刷新页面,页面会从新的 CDN 加载这些资源。 ## 为文档自托管 JavaScript 和 CSS { #self-hosting-javascript-and-css-for-docs } @@ -93,12 +93,12 @@ Swagger UI 会在幕后为你处理这些,但它需要这个“重定向”辅 Swagger UI 使用以下文件: -- `swagger-ui-bundle.js` -- `swagger-ui.css` +- [`swagger-ui-bundle.js`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js) +- [`swagger-ui.css`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css) 而 ReDoc 使用以下文件: -- `redoc.standalone.js` +- [`redoc.standalone.js`](https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js) 之后,你的文件结构可能如下: @@ -122,7 +122,7 @@ Swagger UI 使用以下文件: ### 测试静态文件 { #test-the-static-files } -启动你的应用,并访问 http://127.0.0.1:8000/static/redoc.standalone.js。 +启动你的应用,并访问 [http://127.0.0.1:8000/static/redoc.standalone.js](http://127.0.0.1:8000/static/redoc.standalone.js)。 你应该会看到一个非常长的 **ReDoc** 的 JavaScript 文件。 @@ -180,6 +180,6 @@ Swagger UI 会在幕后为你处理这些,但它需要这个“重定向”辅 ### 测试静态文件 UI { #test-static-files-ui } -现在,你可以断开 WiFi,访问 http://127.0.0.1:8000/docs,并刷新页面。 +现在,你可以断开 WiFi,访问 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs),并刷新页面。 即使没有互联网,你也能看到 API 的文档并与之交互。 diff --git a/docs/zh/docs/how-to/custom-request-and-route.md b/docs/zh/docs/how-to/custom-request-and-route.md index 8b365987ce..79860a5623 100644 --- a/docs/zh/docs/how-to/custom-request-and-route.md +++ b/docs/zh/docs/how-to/custom-request-and-route.md @@ -18,7 +18,7 @@ 一些使用场景包括: -* 将非 JSON 的请求体转换为 JSON(例如 `msgpack`)。 +* 将非 JSON 的请求体转换为 JSON(例如 [`msgpack`](https://msgpack.org/index.html))。 * 解压缩使用 gzip 压缩的请求体。 * 自动记录所有请求体日志。 @@ -32,7 +32,7 @@ /// tip | 提示 -这是一个演示工作原理的示例。如果你需要 Gzip 支持,可以直接使用提供的 [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank}。 +这是一个演示工作原理的示例。如果你需要 Gzip 支持,可以直接使用提供的 [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware)。 /// @@ -66,7 +66,7 @@ 创建一个新的 `Request` 实例需要这两样:`scope` 和 `receive`。 -想了解更多关于 `Request` 的信息,请查看 Starlette 的 Request 文档。 +想了解更多关于 `Request` 的信息,请查看 [Starlette 的 Request 文档](https://www.starlette.dev/requests/)。 /// @@ -82,7 +82,7 @@ /// tip | 提示 -要解决类似问题,使用 `RequestValidationError` 的自定义处理器中的 `body` 往往更简单([处理错误](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank})。 +要解决类似问题,使用 `RequestValidationError` 的自定义处理器中的 `body` 往往更简单([处理错误](../tutorial/handling-errors.md#use-the-requestvalidationerror-body))。 但本示例同样有效,并展示了如何与内部组件交互。 diff --git a/docs/zh/docs/how-to/extending-openapi.md b/docs/zh/docs/how-to/extending-openapi.md index ad8a1d6981..fd39e439fa 100644 --- a/docs/zh/docs/how-to/extending-openapi.md +++ b/docs/zh/docs/how-to/extending-openapi.md @@ -37,7 +37,7 @@ 基于以上信息,你可以用同一个工具函数生成 OpenAPI 架构,并按需覆盖其中的各个部分。 -例如,让我们添加 ReDoc 的 OpenAPI 扩展以包含自定义 Logo。 +例如,让我们添加 [ReDoc 的 OpenAPI 扩展以包含自定义 Logo](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo)。 ### 常规 **FastAPI** { #normal-fastapi } @@ -75,6 +75,6 @@ ### 验证 { #check-it } -当你访问 http://127.0.0.1:8000/redoc 时,你会看到已使用你的自定义 Logo(本例中为 **FastAPI** 的 Logo): +当你访问 [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) 时,你会看到已使用你的自定义 Logo(本例中为 **FastAPI** 的 Logo): diff --git a/docs/zh/docs/how-to/general.md b/docs/zh/docs/how-to/general.md index 2c9f781791..1526ca1872 100644 --- a/docs/zh/docs/how-to/general.md +++ b/docs/zh/docs/how-to/general.md @@ -4,36 +4,40 @@ ## 数据过滤 - 安全性 { #filter-data-security } -为确保不返回超过需要的数据,请阅读 [教程 - 响应模型 - 返回类型](../tutorial/response-model.md){.internal-link target=_blank} 文档。 +为确保不返回超过需要的数据,请阅读 [教程 - 响应模型 - 返回类型](../tutorial/response-model.md) 文档。 + +## 优化响应性能 - 响应模型 - 返回类型 { #optimize-response-performance-response-model-return-type } + +在返回 JSON 数据时优化性能,请使用返回类型或响应模型,这样 Pydantic 会在 Rust 侧处理到 JSON 的序列化,而无需经过 Python。更多内容请阅读 [教程 - 响应模型 - 返回类型](../tutorial/response-model.md) 文档。 ## 文档的标签 - OpenAPI { #documentation-tags-openapi } -在文档界面中添加**路径操作**的标签和进行分组,请阅读 [教程 - 路径操作配置 - Tags 参数](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank} 文档。 +在文档界面中添加**路径操作**的标签和进行分组,请阅读 [教程 - 路径操作配置 - Tags](../tutorial/path-operation-configuration.md#tags) 文档。 ## 文档的概要和描述 - OpenAPI { #documentation-summary-and-description-openapi } -在文档界面中添加**路径操作**的概要和描述,请阅读 [教程 - 路径操作配置 - Summary 和 Description 参数](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank} 文档。 +在文档界面中添加**路径操作**的概要和描述,请阅读 [教程 - 路径操作配置 - Summary 和 Description](../tutorial/path-operation-configuration.md#summary-and-description) 文档。 ## 文档的响应描述 - OpenAPI { #documentation-response-description-openapi } -在文档界面中定义并显示响应描述,请阅读 [教程 - 路径操作配置 - 响应描述](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank} 文档。 +在文档界面中定义并显示响应描述,请阅读 [教程 - 路径操作配置 - 响应描述](../tutorial/path-operation-configuration.md#response-description) 文档。 ## 文档弃用**路径操作** - OpenAPI { #documentation-deprecate-a-path-operation-openapi } -在文档界面中显示弃用的**路径操作**,请阅读 [教程 - 路径操作配置 - 弃用](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank} 文档。 +在文档界面中显示弃用的**路径操作**,请阅读 [教程 - 路径操作配置 - 弃用](../tutorial/path-operation-configuration.md#deprecate-a-path-operation) 文档。 ## 将任何数据转换为 JSON 兼容格式 { #convert-any-data-to-json-compatible } -要将任何数据转换为 JSON 兼容格式,请阅读 [教程 - JSON 兼容编码器](../tutorial/encoder.md){.internal-link target=_blank} 文档。 +要将任何数据转换为 JSON 兼容格式,请阅读 [教程 - JSON 兼容编码器](../tutorial/encoder.md) 文档。 ## OpenAPI 元数据 - 文档 { #openapi-metadata-docs } -要添加 OpenAPI 的元数据,包括许可证、版本、联系方式等,请阅读 [教程 - 元数据和文档 URL](../tutorial/metadata.md){.internal-link target=_blank} 文档。 +要添加 OpenAPI 的元数据,包括许可证、版本、联系方式等,请阅读 [教程 - 元数据和文档 URL](../tutorial/metadata.md) 文档。 ## OpenAPI 自定义 URL { #openapi-custom-url } -要自定义 OpenAPI 的 URL(或删除它),请阅读 [教程 - 元数据和文档 URL](../tutorial/metadata.md#openapi-url){.internal-link target=_blank} 文档。 +要自定义 OpenAPI 的 URL(或删除它),请阅读 [教程 - 元数据和文档 URL](../tutorial/metadata.md#openapi-url) 文档。 ## OpenAPI 文档 URL { #openapi-docs-urls } -要更改自动生成的文档用户界面所使用的 URL,请阅读 [教程 - 元数据和文档 URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}。 +要更改自动生成的文档用户界面所使用的 URL,请阅读 [教程 - 元数据和文档 URL](../tutorial/metadata.md#docs-urls)。 diff --git a/docs/zh/docs/how-to/graphql.md b/docs/zh/docs/how-to/graphql.md index 5384f15137..b33d6759fa 100644 --- a/docs/zh/docs/how-to/graphql.md +++ b/docs/zh/docs/how-to/graphql.md @@ -18,18 +18,18 @@ 以下是一些支持 **ASGI** 的 **GraphQL** 库。你可以将它们与 **FastAPI** 一起使用: -* Strawberry 🍓 - * 提供 面向 FastAPI 的文档 -* Ariadne - * 提供 面向 FastAPI 的文档 -* Tartiflette - * 提供用于 ASGI 集成的 Tartiflette ASGI -* Graphene - * 可配合 starlette-graphene3 使用 +* [Strawberry](https://strawberry.rocks/) 🍓 + * 提供 [面向 FastAPI 的文档](https://strawberry.rocks/docs/integrations/fastapi) +* [Ariadne](https://ariadnegraphql.org/) + * 提供 [面向 FastAPI 的文档](https://ariadnegraphql.org/docs/fastapi-integration) +* [Tartiflette](https://tartiflette.io/) + * 提供用于 ASGI 集成的 [Tartiflette ASGI](https://tartiflette.github.io/tartiflette-asgi/) +* [Graphene](https://graphene-python.org/) + * 可配合 [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3) 使用 ## 使用 Strawberry 的 GraphQL { #graphql-with-strawberry } -如果你需要或想要使用 **GraphQL**,**Strawberry** 是**推荐**的库,因为它的设计与 **FastAPI** 最为接近,全部基于**类型注解**。 +如果你需要或想要使用 **GraphQL**,[**Strawberry**](https://strawberry.rocks/) 是**推荐**的库,因为它的设计与 **FastAPI** 最为接近,全部基于**类型注解**。 根据你的用例,你可能会更喜欢其他库,但如果你问我,我大概率会建议你先试试 **Strawberry**。 @@ -37,24 +37,24 @@ {* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} -你可以在 Strawberry 文档中了解更多信息。 +你可以在 [Strawberry 文档](https://strawberry.rocks/) 中了解更多信息。 -还有关于 将 Strawberry 与 FastAPI 结合使用的文档。 +还有关于 [将 Strawberry 与 FastAPI 结合使用](https://strawberry.rocks/docs/integrations/fastapi) 的文档。 ## Starlette 中较早的 `GraphQLApp` { #older-graphqlapp-from-starlette } -早期版本的 Starlette 包含一个 `GraphQLApp` 类,用于与 Graphene 集成。 +早期版本的 Starlette 包含一个 `GraphQLApp` 类,用于与 [Graphene](https://graphene-python.org/) 集成。 -它已在 Starlette 中被弃用,但如果你的代码使用了它,你可以轻松**迁移**到 starlette-graphene3,它覆盖相同的用例,且接口**几乎完全一致**。 +它已在 Starlette 中被弃用,但如果你的代码使用了它,你可以轻松**迁移**到 [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3),它覆盖相同的用例,且接口**几乎完全一致**。 /// tip | 提示 -如果你需要 GraphQL,我仍然建议看看 Strawberry,因为它基于类型注解而不是自定义类和类型。 +如果你需要 GraphQL,我仍然建议看看 [Strawberry](https://strawberry.rocks/),因为它基于类型注解而不是自定义类和类型。 /// ## 了解更多 { #learn-more } -你可以在 GraphQL 官方文档中了解更多关于 **GraphQL** 的内容。 +你可以在 [GraphQL 官方文档](https://graphql.org/) 中了解更多关于 **GraphQL** 的内容。 你也可以通过上面的链接阅读各个库的更多信息。 diff --git a/docs/zh/docs/how-to/index.md b/docs/zh/docs/how-to/index.md index 980dcd1a65..ff3d8afa0c 100644 --- a/docs/zh/docs/how-to/index.md +++ b/docs/zh/docs/how-to/index.md @@ -8,6 +8,6 @@ /// tip | 提示 -如果你想以系统的方式**学习 FastAPI**(推荐),请阅读 [教程 - 用户指南](../tutorial/index.md){.internal-link target=_blank} 的每一章节。 +如果你想以系统的方式**学习 FastAPI**(推荐),请阅读 [教程 - 用户指南](../tutorial/index.md) 的每一章节。 /// diff --git a/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 2e5445200a..3723eb0327 100644 --- a/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -22,7 +22,7 @@ FastAPI 0.126.0 移除了对 Pydantic v1 的支持,但在一段时间内仍支 ## 官方指南 { #official-guide } -Pydantic 有一份从 v1 迁移到 v2 的官方 迁移指南。 +Pydantic 有一份从 v1 迁移到 v2 的官方[迁移指南](https://docs.pydantic.dev/latest/migration/)。 其中包含变更内容、校验如何更准确更严格、可能的注意事项等。 @@ -30,7 +30,7 @@ Pydantic 有一份从 v1 迁移到 v2 的官方 `bump-pydantic`。 +你可以使用同一 Pydantic 团队提供的[`bump-pydantic`](https://github.com/pydantic/bump-pydantic)。 该工具会帮助你自动修改大部分需要变更的代码。 diff --git a/docs/zh/docs/how-to/testing-database.md b/docs/zh/docs/how-to/testing-database.md index e4a20d8436..57219832bb 100644 --- a/docs/zh/docs/how-to/testing-database.md +++ b/docs/zh/docs/how-to/testing-database.md @@ -1,7 +1,7 @@ # 测试数据库 { #testing-a-database } -你可以在 SQLModel 文档 中学习数据库、SQL 和 SQLModel。🤓 +你可以在[SQLModel 文档](https://sqlmodel.tiangolo.com/)中学习数据库、SQL 和 SQLModel。🤓 -这里有一个关于在 FastAPI 中使用 SQLModel 的小教程:使用 SQLModel 搭配 FastAPI 的教程。✨ +这里有一个[在 FastAPI 中使用 SQLModel 的小教程](https://sqlmodel.tiangolo.com/tutorial/fastapi/)。✨ -该教程包含一个关于 测试 SQL 数据库 的章节。😎 +该教程包含一个关于[测试 SQL 数据库](https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/)的章节。😎 diff --git a/docs/zh/docs/index.md b/docs/zh/docs/index.md index 38e128bf14..a88c25efb1 100644 --- a/docs/zh/docs/index.md +++ b/docs/zh/docs/index.md @@ -11,25 +11,25 @@ FastAPI 框架,高性能,易于学习,高效编码,生产可用

- + Test - + Coverage - + Package version - + Supported Python versions

--- -**文档**: https://fastapi.tiangolo.com +**文档**: [https://fastapi.tiangolo.com/zh](https://fastapi.tiangolo.com/zh) -**源码**: https://github.com/fastapi/fastapi +**源码**: [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi) --- @@ -44,7 +44,7 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Web 框 * **易用**:为易用和易学而设计。更少的文档阅读时间。 * **简短**:最小化代码重复。一次参数声明即可获得多种功能。更少的 bug。 * **健壮**:生产可用级代码。并带有自动生成的交互式文档。 -* **标准化**:基于(并完全兼容)API 的开放标准:OpenAPI(以前称为 Swagger)和 JSON Schema。 +* **标准化**:基于(并完全兼容)API 的开放标准:[OpenAPI](https://github.com/OAI/OpenAPI-Specification)(以前称为 Swagger)和 [JSON Schema](https://json-schema.org/)。 * 基于某内部开发团队在构建生产应用时的测试估算。 @@ -55,51 +55,51 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Web 框 ### Keystone 赞助商 { #keystone-sponsor } {% for sponsor in sponsors.keystone -%} - + {% endfor -%} ### 金牌和银牌赞助商 { #gold-and-silver-sponsors } {% for sponsor in sponsors.gold -%} - + {% endfor -%} {%- for sponsor in sponsors.silver -%} - + {% endfor %} -其他赞助商 +[其他赞助商](https://fastapi.tiangolo.com/zh/fastapi-people/#sponsors) ## 评价 { #opinions } 「_[...] 最近我大量使用 **FastAPI**。[...] 我实际上计划把它用于我团队在 **微软** 的所有 **机器学习服务**。其中一些正在集成进核心 **Windows** 产品以及一些 **Office** 产品。_」 -
Kabir Khan - Microsoft (ref)
+
Kabir Khan - Microsoft (ref)
--- 「_我们采用 **FastAPI** 来构建可查询以获取**预测结果**的 **REST** 服务器。[用于 Ludwig]_」 -
Piero Molino,Yaroslav Dudin,Sai Sumanth Miryala - Uber (ref)
+
Piero Molino,Yaroslav Dudin,Sai Sumanth Miryala - Uber (ref)
--- 「_**Netflix** 很高兴宣布开源我们的**危机管理**编排框架:**Dispatch**![使用 **FastAPI** 构建]_」 -
Kevin Glisson,Marc Vilanova,Forest Monsen - Netflix (ref)
+
Kevin Glisson,Marc Vilanova,Forest Monsen - Netflix (ref)
--- 「_我对 **FastAPI** 兴奋到飞起。它太有趣了!_」 -
Brian Okken - Python Bytes 播客主持人 (ref)
+
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) 播客主持人 (ref)
--- 「_老实说,你构建的东西非常稳健而且打磨得很好。从很多方面看,这就是我想让 **Hug** 成为的样子 —— 看到有人把它做出来真的很鼓舞人心。_」 -
Timothy Crosley - Hug 作者 (ref)
+
Timothy Crosley - [Hug](https://github.com/hugapi/hug) 作者 (ref)
--- @@ -107,27 +107,27 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Web 框 「_我们已经把我们的 **API** 切换到 **FastAPI** [...] 我想你会喜欢它 [...]_」 -
Ines Montani - Matthew Honnibal - Explosion AI 创始人 - spaCy 作者 (ref) - (ref)
+
Ines Montani - Matthew Honnibal - [Explosion AI](https://explosion.ai) 创始人 - [spaCy](https://spacy.io) 作者 (ref) - (ref)
--- 「_如果有人正在构建生产级的 Python API,我强烈推荐 **FastAPI**。它**设计优雅**、**使用简单**且**高度可扩展**,已经成为我们 API 优先开发战略中的**关键组件**,并驱动了许多自动化和服务,比如我们的 Virtual TAC Engineer。_」 -
Deon Pillsbury - Cisco (ref)
+
Deon Pillsbury - Cisco (ref)
--- ## FastAPI 迷你纪录片 { #fastapi-mini-documentary } -在 2025 年末发布了一部FastAPI 迷你纪录片,你可以在线观看: +在 2025 年末发布了一部 [FastAPI 迷你纪录片](https://www.youtube.com/watch?v=mpR8ngthqiE),你可以在线观看: -FastAPI Mini Documentary +FastAPI Mini Documentary ## **Typer**,命令行中的 FastAPI { #typer-the-fastapi-of-clis } - + -如果你要开发一个用于终端的 命令行应用而不是 Web API,看看 **Typer**。 +如果你要开发一个用于终端的 命令行应用而不是 Web API,看看 [**Typer**](https://typer.tiangolo.com/)。 **Typer** 是 FastAPI 的小同胞。它的目标是成为**命令行中的 FastAPI**。⌨️ 🚀 @@ -135,12 +135,12 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Web 框 FastAPI 站在巨人的肩膀之上: -* Starlette 负责 Web 部分。 -* Pydantic 负责数据部分。 +* [Starlette](https://www.starlette.dev/) 负责 Web 部分。 +* [Pydantic](https://docs.pydantic.dev/) 负责数据部分。 ## 安装 { #installation } -创建并激活一个虚拟环境,然后安装 FastAPI: +创建并激活一个 [虚拟环境](https://fastapi.tiangolo.com/zh/virtual-environments/),然后安装 FastAPI:
@@ -199,7 +199,7 @@ async def read_item(item_id: int, q: str | None = None): **Note**: -如果你不确定,请查看文档中 _"In a hurry?"_ 章节的`async` 和 `await`部分。 +如果你不确定,请查看文档中 _"In a hurry?"_ 章节的 [`async` 和 `await`](https://fastapi.tiangolo.com/zh/async/#in-a-hurry) 部分。 @@ -210,7 +210,7 @@ async def read_item(item_id: int, q: str | None = None):
```console -$ fastapi dev main.py +$ fastapi dev ╭────────── FastAPI CLI - Development mode ───────────╮ │ │ @@ -235,19 +235,19 @@ INFO: Application startup complete.
-关于命令 fastapi dev main.py... +关于命令 fastapi dev... -`fastapi dev` 命令会读取你的 `main.py` 文件,检测其中的 **FastAPI** 应用,并使用 Uvicorn 启动服务器。 +`fastapi dev` 命令会读取你的 `main.py` 文件,检测其中的 **FastAPI** 应用,并使用 [Uvicorn](https://www.uvicorn.dev) 启动服务器。 默认情况下,`fastapi dev` 会在本地开发时启用自动重载。 -你可以在 FastAPI CLI 文档中了解更多。 +你可以在 [FastAPI CLI 文档](https://fastapi.tiangolo.com/zh/fastapi-cli/) 中了解更多。
### 检查 { #check-it } -用浏览器打开 http://127.0.0.1:8000/items/5?q=somequery。 +用浏览器打开 [http://127.0.0.1:8000/items/5?q=somequery](http://127.0.0.1:8000/items/5?q=somequery)。 你会看到如下 JSON 响应: @@ -264,17 +264,17 @@ INFO: Application startup complete. ### 交互式 API 文档 { #interactive-api-docs } -现在访问 http://127.0.0.1:8000/docs。 +现在访问 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 -你会看到自动生成的交互式 API 文档(由 Swagger UI 提供): +你会看到自动生成的交互式 API 文档(由 [Swagger UI](https://github.com/swagger-api/swagger-ui) 提供): ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) ### 可选的 API 文档 { #alternative-api-docs } -然后访问 http://127.0.0.1:8000/redoc。 +然后访问 [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)。 -你会看到另一个自动生成的文档(由 ReDoc 提供): +你会看到另一个自动生成的文档(由 [ReDoc](https://github.com/Rebilly/ReDoc) 提供): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -316,7 +316,7 @@ def update_item(item_id: int, item: Item): ### 交互式 API 文档升级 { #interactive-api-docs-upgrade } -现在访问 http://127.0.0.1:8000/docs。 +现在访问 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 * 交互式 API 文档会自动更新,并包含新的请求体: @@ -332,7 +332,7 @@ def update_item(item_id: int, item: Item): ### 可选文档升级 { #alternative-api-docs-upgrade } -再访问 http://127.0.0.1:8000/redoc。 +再访问 [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)。 * 可选文档同样会体现新的查询参数和请求体: @@ -442,7 +442,7 @@ item: Item * 功能强大且易用的 **依赖注入** 系统。 * 安全与认证,包括对 **OAuth2**、**JWT tokens** 和 **HTTP Basic** 认证的支持。 * 更高级(但同样简单)的 **多层嵌套 JSON 模型** 声明技巧(得益于 Pydantic)。 -* 通过 Strawberry 等库进行 **GraphQL** 集成。 +* 通过 [Strawberry](https://strawberry.rocks) 等库进行 **GraphQL** 集成。 * 许多额外特性(归功于 Starlette),例如: * **WebSockets** * 基于 HTTPX 和 `pytest` 的极其简单的测试 @@ -452,24 +452,10 @@ item: Item ### 部署你的应用(可选) { #deploy-your-app-optional } -你可以选择把 FastAPI 应用部署到 FastAPI Cloud,如果还没有的话去加入候补名单吧。🚀 +你可以选择把 FastAPI 应用部署到 [FastAPI Cloud](https://fastapicloud.com),如果还没有的话去加入候补名单吧。🚀 如果你已经有 **FastAPI Cloud** 账号(我们从候补名单邀请了你 😉),你可以用一个命令部署你的应用。 -部署前,先确认已登录: - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -然后部署你的应用: -
```console @@ -488,7 +474,7 @@ Deploying to FastAPI Cloud... #### 关于 FastAPI Cloud { #about-fastapi-cloud } -**FastAPI Cloud** 由 **FastAPI** 的同一位作者和团队打造。 +**[FastAPI Cloud](https://fastapicloud.com)** 由 **FastAPI** 的同一位作者和团队打造。 它让你以最小的工作量就能**构建**、**部署**并**访问**一个 API。 @@ -504,9 +490,9 @@ FastAPI 是开源且基于标准的。你可以部署 FastAPI 应用到你选择 ## 性能 { #performance } -独立机构 TechEmpower 的基准测试显示,运行在 Uvicorn 下的 **FastAPI** 应用是最快的 Python 框架之一,仅次于 Starlette 和 Uvicorn 本身(FastAPI 内部使用它们)。(*) +独立机构 TechEmpower 的基准测试显示,运行在 Uvicorn 下的 **FastAPI** 应用是 [最快的 Python 框架之一](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7),仅次于 Starlette 和 Uvicorn 本身(FastAPI 内部使用它们)。(*) -想了解更多,请参阅基准测试章节。 +想了解更多,请参阅 [基准测试](https://fastapi.tiangolo.com/zh/benchmarks/) 章节。 ## 依赖项 { #dependencies } @@ -518,19 +504,19 @@ FastAPI 依赖 Pydantic 和 Starlette。 Pydantic 使用: -* email-validator - 用于 email 校验。 +* [`email-validator`](https://github.com/JoshData/python-email-validator) - 用于 email 校验。 Starlette 使用: -* httpx - 使用 `TestClient` 时需要。 -* jinja2 - 使用默认模板配置时需要。 -* python-multipart - 使用 `request.form()` 支持表单「解析」时需要。 +* [`httpx`](https://www.python-httpx.org) - 使用 `TestClient` 时需要。 +* [`jinja2`](https://jinja.palletsprojects.com) - 使用默认模板配置时需要。 +* [`python-multipart`](https://github.com/Kludex/python-multipart) - 使用 `request.form()` 支持表单「解析」时需要。 FastAPI 使用: -* uvicorn - 加载并提供你的应用的服务器。包含 `uvicorn[standard]`,其中包含高性能服务所需的一些依赖(例如 `uvloop`)。 +* [`uvicorn`](https://www.uvicorn.dev) - 加载并提供你的应用的服务器。包含 `uvicorn[standard]`,其中包含高性能服务所需的一些依赖(例如 `uvloop`)。 * `fastapi-cli[standard]` - 提供 `fastapi` 命令。 - * 其中包含 `fastapi-cloud-cli`,它允许你将 FastAPI 应用部署到 FastAPI Cloud。 + * 其中包含 `fastapi-cloud-cli`,它允许你将 FastAPI 应用部署到 [FastAPI Cloud](https://fastapicloud.com)。 ### 不包含 `standard` 依赖 { #without-standard-dependencies } @@ -546,13 +532,13 @@ FastAPI 使用: 额外的 Pydantic 可选依赖: -* pydantic-settings - 用于配置管理。 -* pydantic-extra-types - 用于在 Pydantic 中使用的额外类型。 +* [`pydantic-settings`](https://docs.pydantic.dev/latest/usage/pydantic_settings/) - 用于配置管理。 +* [`pydantic-extra-types`](https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/) - 用于在 Pydantic 中使用的额外类型。 额外的 FastAPI 可选依赖: -* orjson - 使用 `ORJSONResponse` 时需要。 -* ujson - 使用 `UJSONResponse` 时需要。 +* [`orjson`](https://github.com/ijl/orjson) - 使用 `ORJSONResponse` 时需要。 +* [`ujson`](https://github.com/esnme/ultrajson) - 使用 `UJSONResponse` 时需要。 ## 许可协议 { #license } diff --git a/docs/zh/docs/project-generation.md b/docs/zh/docs/project-generation.md index a6ad9f94ac..8cc50c0963 100644 --- a/docs/zh/docs/project-generation.md +++ b/docs/zh/docs/project-generation.md @@ -4,7 +4,7 @@ 你可以使用此模板开始,它已经为你完成了大量的初始设置、安全性、数据库以及一些 API 端点。 -GitHub 仓库: Full Stack FastAPI Template +GitHub 仓库:[Full Stack FastAPI Template](https://github.com/tiangolo/full-stack-fastapi-template) ## FastAPI全栈模板 - 技术栈和特性 { #full-stack-fastapi-template-technology-stack-and-features } diff --git a/docs/zh/docs/python-types.md b/docs/zh/docs/python-types.md index 4824b7558d..9b2fceb98e 100644 --- a/docs/zh/docs/python-types.md +++ b/docs/zh/docs/python-types.md @@ -269,7 +269,7 @@ def some_function(data: Any): ## Pydantic 模型 { #pydantic-models } -Pydantic 是一个用于执行数据校验的 Python 库。 +[Pydantic](https://docs.pydantic.dev/) 是一个用于执行数据校验的 Python 库。 你将数据的“结构”声明为带有属性的类。 @@ -285,13 +285,13 @@ def some_function(data: Any): /// info | 信息 -想了解更多关于 Pydantic 的信息,请查看其文档。 +想了解更多关于 [Pydantic](https://docs.pydantic.dev/) 的信息,请查看其文档。 /// **FastAPI** 完全建立在 Pydantic 之上。 -你会在[教程 - 用户指南](tutorial/index.md){.internal-link target=_blank}中看到更多的实战示例。 +你会在[教程 - 用户指南](tutorial/index.md)中看到更多的实战示例。 ## 带元数据注解的类型提示 { #type-hints-with-metadata-annotations } @@ -337,12 +337,12 @@ Python 本身不会对这个 `Annotated` 做任何处理。对于编辑器和其 * 使用 OpenAPI 记录 API: * 然后用于自动生成交互式文档界面。 -这些听起来可能有点抽象。别担心。你会在[教程 - 用户指南](tutorial/index.md){.internal-link target=_blank}中看到所有这些的实际效果。 +这些听起来可能有点抽象。别担心。你会在[教程 - 用户指南](tutorial/index.md)中看到所有这些的实际效果。 重要的是,通过使用标准的 Python 类型,而且只在一个地方声明(而不是添加更多类、装饰器等),**FastAPI** 会为你完成大量工作。 /// info | 信息 -如果你已经读完所有教程,又回来想进一步了解类型,一个不错的资源是 `mypy` 的“速查表”。 +如果你已经读完所有教程,又回来想进一步了解类型,一个不错的资源是 [`mypy` 的“速查表”](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html)。 /// diff --git a/docs/zh/docs/tutorial/background-tasks.md b/docs/zh/docs/tutorial/background-tasks.md index d73fee4299..975bb2688c 100644 --- a/docs/zh/docs/tutorial/background-tasks.md +++ b/docs/zh/docs/tutorial/background-tasks.md @@ -61,7 +61,7 @@ ## 技术细节 { #technical-details } -`BackgroundTasks` 类直接来自 `starlette.background`。 +`BackgroundTasks` 类直接来自 [`starlette.background`](https://www.starlette.dev/background/)。 它被直接导入/包含到FastAPI以便你可以从 `fastapi` 导入,并避免意外从 `starlette.background` 导入备用的 `BackgroundTask` (后面没有 `s`)。 @@ -69,11 +69,11 @@ 在FastAPI中仍然可以单独使用 `BackgroundTask`,但您必须在代码中创建对象,并返回包含它的Starlette `Response`。 -更多细节查看 Starlette 后台任务的官方文档. +更多细节查看 [Starlette 后台任务的官方文档](https://www.starlette.dev/background/)。 ## 告诫 { #caveat } -如果您需要执行繁重的后台计算,并且不一定需要由同一进程运行(例如,您不需要共享内存、变量等),那么使用其他更大的工具(如 Celery)可能更好。 +如果您需要执行繁重的后台计算,并且不一定需要由同一进程运行(例如,您不需要共享内存、变量等),那么使用其他更大的工具(如 [Celery](https://docs.celeryq.dev))可能更好。 它们往往需要更复杂的配置,即消息/作业队列管理器,如RabbitMQ或Redis,但它们允许您在多个进程中运行后台任务,甚至是在多个服务器中。 diff --git a/docs/zh/docs/tutorial/bigger-applications.md b/docs/zh/docs/tutorial/bigger-applications.md index a667d596f8..74522f8384 100644 --- a/docs/zh/docs/tutorial/bigger-applications.md +++ b/docs/zh/docs/tutorial/bigger-applications.md @@ -123,7 +123,7 @@ from app.routers import items 我们正在使用虚构的请求首部来简化此示例。 -但在实际情况下,使用集成的[安全性实用工具](security/index.md){.internal-link target=_blank}会得到更好的效果。 +但在实际情况下,使用集成的[安全性实用工具](security/index.md)会得到更好的效果。 /// @@ -169,7 +169,7 @@ async def read_item(item_id: str): /// tip | 提示 -请注意,和[*路径操作装饰器*中的依赖项](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}很类似,没有值会被传递给你的*路径操作函数*。 +请注意,和[*路径操作装饰器*中的依赖项](dependencies/dependencies-in-path-operation-decorators.md)很类似,没有值会被传递给你的*路径操作函数*。 /// @@ -185,8 +185,8 @@ async def read_item(item_id: str): * 所有的路径操作都将包含预定义的 `responses`。 * 所有的这些*路径操作*都将在自身之前计算/执行 `dependencies` 列表。 * 如果你还在一个具体的*路径操作*中声明了依赖项,**它们也会被执行**。 - * 路由器的依赖项最先执行,然后是[装饰器中的 `dependencies`](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank},再然后是普通的参数依赖项。 - * 你还可以添加[具有 `scopes` 的 `Security` 依赖项](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}。 + * 路由器的依赖项最先执行,然后是[装饰器中的 `dependencies`](dependencies/dependencies-in-path-operation-decorators.md),再然后是普通的参数依赖项。 + * 你还可以添加[具有 `scopes` 的 `Security` 依赖项](../advanced/security/oauth2-scopes.md)。 /// tip | 提示 @@ -303,7 +303,7 @@ from ...dependencies import get_token_header 你可以像平常一样导入并创建一个 `FastAPI` 类。 -我们甚至可以声明[全局依赖项](dependencies/global-dependencies.md){.internal-link target=_blank},它会和每个 `APIRouter` 的依赖项组合在一起: +我们甚至可以声明[全局依赖项](dependencies/global-dependencies.md),它会和每个 `APIRouter` 的依赖项组合在一起: {* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} @@ -353,7 +353,7 @@ from .routers import items, users from app.routers import items, users ``` -要了解有关 Python 包和模块的更多信息,请查阅关于 Modules 的 Python 官方文档。 +要了解有关 Python 包和模块的更多信息,请查阅[关于 Modules 的 Python 官方文档](https://docs.python.org/3/tutorial/modules.html)。 /// @@ -451,7 +451,7 @@ from .routers.users import router 它将与通过 `app.include_router()` 添加的所有其他*路径操作*一起正常运行。 -/// info | 特别的技术细节 +/// info | 非常技术细节 **注意**:这是一个非常技术性的细节,你也许可以**直接跳过**。 @@ -465,6 +465,37 @@ from .routers.users import router /// +## 在 `pyproject.toml` 中配置 `entrypoint` { #configure-the-entrypoint-in-pyproject-toml } + +因为你的 FastAPI `app` 对象位于 `app/main.py` 中,你可以在 `pyproject.toml` 中这样配置 `entrypoint`: + +```toml +[tool.fastapi] +entrypoint = "app.main:app" +``` + +等价于像这样导入: + +```python +from app.main import app +``` + +这样 `fastapi` 命令就知道到哪里去找到你的应用了。 + +/// Note | 注意 + +你也可以把路径传给命令,比如: + +```console +$ fastapi dev app/main.py +``` + +但是每次调用 `fastapi` 命令时,你都需要记得传入正确的路径。 + +另外,其他工具可能找不到它,比如 [VS Code 扩展](../editor-support.md) 或 [FastAPI Cloud](https://fastapicloud.com),因此推荐在 `pyproject.toml` 中使用 `entrypoint`。 + +/// + ## 查看自动化的 API 文档 { #check-the-automatic-api-docs } 现在,运行你的应用: @@ -472,14 +503,14 @@ from .routers.users import router
```console -$ fastapi dev app/main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-然后打开位于 http://127.0.0.1:8000/docs 的文档。 +然后打开位于 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) 的文档。 你将看到使用了正确路径(和前缀)和正确标签的自动化 API 文档,包括了来自所有子模块的路径: diff --git a/docs/zh/docs/tutorial/body-nested-models.md b/docs/zh/docs/tutorial/body-nested-models.md index fe6902e83f..93a34da553 100644 --- a/docs/zh/docs/tutorial/body-nested-models.md +++ b/docs/zh/docs/tutorial/body-nested-models.md @@ -95,7 +95,7 @@ Pydantic 模型的每个属性都具有类型。 除了普通的单一值类型(如 `str`、`int`、`float` 等)外,你还可以使用从 `str` 继承的更复杂的单一值类型。 -要了解所有的可用选项,请查看 Pydantic 的类型概览。你将在下一章节中看到一些示例。 +要了解所有的可用选项,请查看 [Pydantic 的类型概览](https://docs.pydantic.dev/latest/concepts/types/)。你将在下一章节中看到一些示例。 例如,在 `Image` 模型中我们有一个 `url` 字段,我们可以把它声明为 Pydantic 的 `HttpUrl`,而不是 `str`: diff --git a/docs/zh/docs/tutorial/body-updates.md b/docs/zh/docs/tutorial/body-updates.md index 000201de99..5b181642cb 100644 --- a/docs/zh/docs/tutorial/body-updates.md +++ b/docs/zh/docs/tutorial/body-updates.md @@ -2,7 +2,7 @@ ## 用 `PUT` 替换式更新 { #update-replacing-with-put } -更新数据可以使用 HTTP `PUT` 操作。 +更新数据可以使用 [HTTP `PUT`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) 操作。 把输入数据转换为以 JSON 格式存储的数据(比如,使用 NoSQL 数据库时),可以使用 `jsonable_encoder`。例如,把 `datetime` 转换为 `str`。 @@ -28,7 +28,7 @@ ## 用 `PATCH` 进行部分更新 { #partial-updates-with-patch } -也可以使用 HTTP `PATCH` 操作对数据进行*部分*更新。 +也可以使用 [HTTP `PATCH`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) 操作对数据进行*部分*更新。 也就是说,你只需发送想要更新的数据,其余数据保持不变。 @@ -95,6 +95,6 @@ 因此,如果希望接收的部分更新可以省略所有属性,则需要一个所有属性都标记为可选(带默认值或 `None`)的模型。 -为了区分用于**更新**(全部可选)和用于**创建**(必填)的模型,可以参考[更多模型](extra-models.md){.internal-link target=_blank} 中介绍的思路。 +为了区分用于**更新**(全部可选)和用于**创建**(必填)的模型,可以参考[更多模型](extra-models.md) 中介绍的思路。 /// diff --git a/docs/zh/docs/tutorial/body.md b/docs/zh/docs/tutorial/body.md index 4a72ba17c5..0a4c9c5e53 100644 --- a/docs/zh/docs/tutorial/body.md +++ b/docs/zh/docs/tutorial/body.md @@ -6,7 +6,7 @@ 你的 API 几乎总是需要发送**响应体**。但客户端不一定总是要发送**请求体**,有时它们只请求某个路径,可能带一些查询参数,但不会发送请求体。 -使用 Pydantic 模型来声明**请求体**,能充分利用它的功能和优点。 +使用 [Pydantic](https://docs.pydantic.dev/) 模型来声明**请求体**,能充分利用它的功能和优点。 /// info | 信息 @@ -72,7 +72,7 @@ * 数据无效时返回清晰的错误信息,并指出错误数据的确切位置和内容。 * 把接收的数据赋值给参数 `item`。 * 因为你把函数中的参数类型声明为 `Item`,所以还能获得所有属性及其类型的编辑器支持(补全等)。 -* 为你的模型生成 JSON Schema 定义,如果对你的项目有意义,还可以在其他地方使用它们。 +* 为你的模型生成 [JSON Schema](https://json-schema.org) 定义,如果对你的项目有意义,还可以在其他地方使用它们。 * 这些 schema 会成为生成的 OpenAPI Schema 的一部分,并被自动文档的 UIs 使用。 ## 自动文档 { #automatic-docs } @@ -101,15 +101,15 @@ 我们甚至对 Pydantic 本身做了一些改动以支持这些功能。 -上面的截图来自 Visual Studio Code。 +上面的截图来自 [Visual Studio Code](https://code.visualstudio.com)。 -但使用 PyCharm 和大多数其他 Python 编辑器,你也会获得相同的编辑器支持: +但使用 [PyCharm](https://www.jetbrains.com/pycharm/) 和大多数其他 Python 编辑器,你也会获得相同的编辑器支持: /// tip | 提示 -如果你使用 PyCharm 作为编辑器,可以使用 Pydantic PyCharm 插件。 +如果你使用 [PyCharm](https://www.jetbrains.com/pycharm/) 作为编辑器,可以使用 [Pydantic PyCharm 插件](https://github.com/koxudaxi/pydantic-pycharm-plugin/)。 它能改进对 Pydantic 模型的编辑器支持,包括: @@ -161,4 +161,4 @@ FastAPI 会根据默认值 `= None` 知道 `q` 的值不是必填的。 ## 不使用 Pydantic { #without-pydantic } -即便不使用 Pydantic 模型也能使用 **Body** 参数。详见[请求体 - 多参数:请求体中的单值](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}。 +即便不使用 Pydantic 模型也能使用 **Body** 参数。详见[请求体 - 多参数:请求体中的单值](body-multiple-params.md#singular-values-in-body)。 diff --git a/docs/zh/docs/tutorial/cors.md b/docs/zh/docs/tutorial/cors.md index 2e271ec758..ebea43edba 100644 --- a/docs/zh/docs/tutorial/cors.md +++ b/docs/zh/docs/tutorial/cors.md @@ -1,6 +1,6 @@ # CORS(跨域资源共享) { #cors-cross-origin-resource-sharing } -CORS 或者「跨域资源共享」 指浏览器中运行的前端拥有与后端通信的 JavaScript 代码,而后端处于与前端不同的「源」的情况。 +[CORS 或者「跨域资源共享」](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) 指浏览器中运行的前端拥有与后端通信的 JavaScript 代码,而后端处于与前端不同的「源」的情况。 ## 源 { #origin } @@ -55,10 +55,10 @@ * `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_headers` - 一个允许跨域请求的 HTTP 请求头列表。默认为 `[]`。你可以使用 `['*']` 允许所有的请求头。`Accept`、`Accept-Language`、`Content-Language` 以及 `Content-Type` 这几个请求头在[简单 CORS 请求](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests)中总是被允许。 * `allow_credentials` - 指示跨域请求支持 cookies。默认是 `False`。 - 当 `allow_credentials` 设为 `True` 时,`allow_origins`、`allow_methods` 和 `allow_headers` 都不能设为 `['*']`。它们必须显式指定。 + 当 `allow_credentials` 设为 `True` 时,`allow_origins`、`allow_methods` 和 `allow_headers` 都不能设为 `['*']`。它们必须[显式指定](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards)。 * `expose_headers` - 指示可以被浏览器访问的响应头。默认为 `[]`。 * `max_age` - 设定浏览器缓存 CORS 响应的最长时间,单位是秒。默认为 `600`。 @@ -77,7 +77,7 @@ ## 更多信息 { #more-info } -更多关于 CORS 的信息,请查看 Mozilla CORS 文档。 +更多关于 CORS 的信息,请查看 [Mozilla CORS 文档](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)。 /// note | 技术细节 diff --git a/docs/zh/docs/tutorial/debugging.md b/docs/zh/docs/tutorial/debugging.md index 1ff7d61275..19e6f8a612 100644 --- a/docs/zh/docs/tutorial/debugging.md +++ b/docs/zh/docs/tutorial/debugging.md @@ -70,7 +70,7 @@ from myapp import app /// info | 信息 -更多信息请检查 Python 官方文档. +更多信息请检查 [Python 官方文档](https://docs.python.org/3/library/__main__.html). /// diff --git a/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index 23412e4650..a3b2e6a41e 100644 --- a/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -32,7 +32,7 @@ 本例中,使用的是自定义响应头 `X-Key` 和 `X-Token`。 -但实际开发中,尤其是在实现安全措施时,最好使用 FastAPI 内置的[安全工具](../security/index.md){.internal-link target=_blank}(详见下一章)。 +但实际开发中,尤其是在实现安全措施时,最好使用 FastAPI 内置的[安全工具(下一章)](../security/index.md)。 /// @@ -62,7 +62,7 @@ ## 为一组路径操作定义依赖项 { #dependencies-for-a-group-of-path-operations } -稍后,[大型应用 - 多文件](../../tutorial/bigger-applications.md){.internal-link target=_blank}一章中会介绍如何使用多个文件创建大型应用程序,在这一章中,您将了解到如何为一组*路径操作*声明单个 `dependencies` 参数。 +稍后,[大型应用 - 多文件](../../tutorial/bigger-applications.md)一章中会介绍如何使用多个文件创建大型应用程序,在这一章中,您将了解到如何为一组*路径操作*声明单个 `dependencies` 参数。 ## 全局依赖项 { #global-dependencies } diff --git a/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md index 413dedb96b..a365bccf04 100644 --- a/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md @@ -14,8 +14,8 @@ FastAPI 支持那些在完成后执行一些`@contextlib.contextmanager` 或 -* `@contextlib.asynccontextmanager` +* [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) 或 +* [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) 都可以作为 **FastAPI** 的依赖项。 @@ -87,7 +87,7 @@ FastAPI 支持那些在完成后执行一些上下文管理器。 +这要归功于 Python 的[上下文管理器](https://docs.python.org/3/library/contextlib.html)。 **FastAPI** 在内部使用它们来实现这一点。 @@ -111,7 +111,7 @@ FastAPI 支持那些在完成后执行一些你可以用 `with` 来读取文件: +例如,[你可以用 `with` 来读取文件](https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files): ```Python with open("./somefile.txt") as f: @@ -265,7 +265,7 @@ with open("./somefile.txt") as f: /// -在 Python 中,你可以通过创建一个带有 `__enter__()` 和 `__exit__()` 方法的类来创建上下文管理器。 +在 Python 中,你可以通过[创建一个带有 `__enter__()` 和 `__exit__()` 方法的类](https://docs.python.org/3/reference/datamodel.html#context-managers)来创建上下文管理器。 你也可以在 **FastAPI** 的带有 `yield` 的依赖中,使用依赖函数内部的 `with` 或 `async with` 语句来使用它们: @@ -275,8 +275,8 @@ with open("./somefile.txt") as f: 另一种创建上下文管理器的方式是: -* `@contextlib.contextmanager` 或 -* `@contextlib.asynccontextmanager` +* [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) 或 +* [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) 用它们去装饰一个只包含单个 `yield` 的函数。 diff --git a/docs/zh/docs/tutorial/dependencies/global-dependencies.md b/docs/zh/docs/tutorial/dependencies/global-dependencies.md index e33aab65cc..cf083f053d 100644 --- a/docs/zh/docs/tutorial/dependencies/global-dependencies.md +++ b/docs/zh/docs/tutorial/dependencies/global-dependencies.md @@ -2,14 +2,14 @@ 有时,我们要为整个应用添加依赖项。 -通过与[将 `dependencies` 添加到*路径操作装饰器*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} 类似的方式,可以把依赖项添加至整个 `FastAPI` 应用。 +通过与[将 `dependencies` 添加到*路径操作装饰器*](dependencies-in-path-operation-decorators.md) 类似的方式,可以把依赖项添加至整个 `FastAPI` 应用。 这样一来,就可以为所有*路径操作*应用该依赖项: {* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *} -[将 `dependencies` 添加到*路径操作装饰器*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} 一章的思路均适用于全局依赖项, 在本例中,这些依赖项可以用于应用中的所有*路径操作*。 +[将 `dependencies` 添加到*路径操作装饰器*](dependencies-in-path-operation-decorators.md) 一章的思路均适用于全局依赖项, 在本例中,这些依赖项可以用于应用中的所有*路径操作*。 ## 为一组路径操作定义依赖项 { #dependencies-for-groups-of-path-operations } -稍后,[大型应用 - 多文件](../../tutorial/bigger-applications.md){.internal-link target=_blank}一章中会介绍如何使用多个文件创建大型应用程序,在这一章中,您将了解到如何为一组*路径操作*声明单个 `dependencies` 参数。 +稍后,[大型应用 - 多文件](../../tutorial/bigger-applications.md)一章中会介绍如何使用多个文件创建大型应用程序,在这一章中,你将了解到如何为一组*路径操作*声明单个 `dependencies` 参数。 diff --git a/docs/zh/docs/tutorial/dependencies/index.md b/docs/zh/docs/tutorial/dependencies/index.md index 7db9ef9d95..939470f409 100644 --- a/docs/zh/docs/tutorial/dependencies/index.md +++ b/docs/zh/docs/tutorial/dependencies/index.md @@ -57,7 +57,7 @@ FastAPI 在 0.95.0 版本中新增了对 `Annotated` 的支持(并开始推荐 如果你的版本较旧,尝试使用 `Annotated` 会报错。 -在使用 `Annotated` 之前,请确保[升级 FastAPI 版本](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}到至少 0.95.1。 +在使用 `Annotated` 之前,请确保[升级 FastAPI 版本](../../deployment/versions.md#upgrading-the-fastapi-versions)到至少 0.95.1。 /// @@ -152,7 +152,7 @@ commons: Annotated[dict, Depends(common_parameters)] /// note | 注意 -如果不了解异步,请参阅文档中关于 `async` 和 `await` 的章节:[异步:*“着急了?”*](../../async.md#in-a-hurry){.internal-link target=_blank}。 +如果不了解异步,请参阅文档中关于 `async` 和 `await` 的章节:[异步:*“着急了?”*](../../async.md#in-a-hurry)。 /// diff --git a/docs/zh/docs/tutorial/encoder.md b/docs/zh/docs/tutorial/encoder.md index 88be497493..8327ab6c7c 100644 --- a/docs/zh/docs/tutorial/encoder.md +++ b/docs/zh/docs/tutorial/encoder.md @@ -12,7 +12,7 @@ 例如,它不接收`datetime`这类的对象,因为这些对象与JSON不兼容。 -因此,`datetime`对象必须转换为包含ISO 格式的`str`类型对象。 +因此,`datetime`对象必须转换为包含[ISO 格式](https://en.wikipedia.org/wiki/ISO_8601)的`str`类型对象。 同样,这个数据库也不会接收Pydantic模型(带有属性的对象),而只接收`dict`。 @@ -24,7 +24,7 @@ 在这个例子中,它将Pydantic模型转换为`dict`,并将`datetime`转换为`str`。 -调用它的结果后就可以使用Python标准编码中的`json.dumps()`。 +调用它的结果后就可以使用Python标准编码中的[`json.dumps()`](https://docs.python.org/3/library/json.html#json.dumps)。 这个操作不会返回一个包含JSON格式(作为字符串)数据的庞大的`str`。它将返回一个Python标准数据结构(例如`dict`),其值和子值都与JSON兼容。 diff --git a/docs/zh/docs/tutorial/extra-data-types.md b/docs/zh/docs/tutorial/extra-data-types.md index 2cefd163d3..76748a7a38 100644 --- a/docs/zh/docs/tutorial/extra-data-types.md +++ b/docs/zh/docs/tutorial/extra-data-types.md @@ -36,7 +36,7 @@ * `datetime.timedelta`: * 一个 Python `datetime.timedelta`. * 在请求和响应中将表示为 `float` 代表总秒数。 - * Pydantic 也允许将其表示为 "ISO 8601 时间差异编码", 查看文档了解更多信息。 + * Pydantic 也允许将其表示为 "ISO 8601 时间差异编码", [查看文档了解更多信息](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers)。 * `frozenset`: * 在请求和响应中,作为 `set` 对待: * 在请求中,列表将被读取,消除重复,并将其转换为一个 `set`。 @@ -49,7 +49,7 @@ * `Decimal`: * 标准的 Python `Decimal`。 * 在请求和响应中被当做 `float` 一样处理。 -* 您可以在这里检查所有有效的 Pydantic 数据类型: Pydantic data types. +* 您可以在这里检查所有有效的 Pydantic 数据类型: [Pydantic data types](https://docs.pydantic.dev/latest/usage/types/types/)。 ## 例子 { #example } diff --git a/docs/zh/docs/tutorial/extra-models.md b/docs/zh/docs/tutorial/extra-models.md index 09baa47319..0ad35cc4fc 100644 --- a/docs/zh/docs/tutorial/extra-models.md +++ b/docs/zh/docs/tutorial/extra-models.md @@ -12,7 +12,7 @@ 不要存储用户的明文密码。始终只存储之后可用于校验的“安全哈希”。 -如果你还不了解,可以在[安全性章节](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}中学习什么是“密码哈希”。 +如果你还不了解,可以在[安全性章节](security/simple-oauth2.md#password-hashing)中学习什么是“密码哈希”。 /// @@ -108,7 +108,7 @@ UserInDB(**user_dict) UserInDB(**user_in.model_dump()) ``` -……因为 `user_in.model_dump()` 是 `dict`,在传递给 `UserInDB` 时,把 `**` 加在 `user_in.model_dump()` 前,可以让 Python 进行解包。 +...因为 `user_in.model_dump()` 是 `dict`,在传递给 `UserInDB` 时,把 `**` 加在 `user_in.model_dump()` 前,可以让 Python 进行解包。 这样,就可以用其它 Pydantic 模型中的数据生成 Pydantic 模型。 @@ -120,7 +120,7 @@ UserInDB(**user_in.model_dump()) UserInDB(**user_in.model_dump(), hashed_password=hashed_password) ``` -……输出结果如下: +...输出结果如下: ```Python UserInDB( @@ -162,11 +162,11 @@ UserInDB( 在 OpenAPI 中会用 `anyOf` 表示。 -为此,请使用 Python 标准类型提示 `typing.Union`: +为此,请使用 Python 标准类型提示 [`typing.Union`](https://docs.python.org/3/library/typing.html#typing.Union): /// note | 注意 -定义 `Union` 类型时,要把更具体的类型写在前面,然后是不太具体的类型。下例中,更具体的 `PlaneItem` 位于 `Union[PlaneItem, CarItem]` 中的 `CarItem` 之前。 +定义 [`Union`](https://docs.pydantic.dev/latest/concepts/types/#unions) 类型时,要把更具体的类型写在前面,然后是不太具体的类型。下例中,更具体的 `PlaneItem` 位于 `Union[PlaneItem, CarItem]` 中的 `CarItem` 之前。 /// diff --git a/docs/zh/docs/tutorial/first-steps.md b/docs/zh/docs/tutorial/first-steps.md index 4c23807b8f..78db1fefc0 100644 --- a/docs/zh/docs/tutorial/first-steps.md +++ b/docs/zh/docs/tutorial/first-steps.md @@ -11,7 +11,7 @@
```console -$ fastapi dev main.py +$ fastapi dev FastAPI Starting development server 🚀 @@ -58,7 +58,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ### 查看 { #check-it } -打开浏览器访问 http://127.0.0.1:8000。 +打开浏览器访问 [http://127.0.0.1:8000](http://127.0.0.1:8000)。 你将看到如下的 JSON 响应: @@ -68,17 +68,17 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ### 交互式 API 文档 { #interactive-api-docs } -跳转到 http://127.0.0.1:8000/docs。 +跳转到 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 -你将会看到自动生成的交互式 API 文档(由 Swagger UI 提供): +你将会看到自动生成的交互式 API 文档(由 [Swagger UI](https://github.com/swagger-api/swagger-ui) 提供): ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) ### 可选的 API 文档 { #alternative-api-docs } -前往 http://127.0.0.1:8000/redoc。 +前往 [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)。 -你将会看到可选的自动生成文档 (由 ReDoc 提供): +你将会看到可选的自动生成文档 (由 [ReDoc](https://github.com/Rebilly/ReDoc) 提供): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -92,7 +92,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) #### API「模式」 { #api-schema } -在这种场景下,OpenAPI 是一种规定如何定义 API 模式的规范。 +在这种场景下,[OpenAPI](https://github.com/OAI/OpenAPI-Specification) 是一种规定如何定义 API 模式的规范。 「模式」的定义包括你的 API 路径,以及它们可能使用的参数等等。 @@ -110,7 +110,7 @@ OpenAPI 为你的 API 定义 API 模式。该模式中包含了你的 API 发送 如果你对原始的 OpenAPI 模式长什么样子感到好奇,FastAPI 自动生成了包含所有 API 描述的 JSON(模式)。 -你可以直接在:http://127.0.0.1:8000/openapi.json 看到它。 +你可以直接在:[http://127.0.0.1:8000/openapi.json](http://127.0.0.1:8000/openapi.json) 看到它。 它将显示以如下内容开头的 JSON: @@ -143,9 +143,58 @@ OpenAPI 为你的 API 定义 API 模式。该模式中包含了你的 API 发送 你还可以使用它自动生成与你的 API 进行通信的客户端代码。例如 web 前端,移动端或物联网嵌入程序。 +### 在 `pyproject.toml` 中配置应用 `entrypoint` { #configure-the-app-entrypoint-in-pyproject-toml } + +你可以在 `pyproject.toml` 文件中配置应用的位置,例如: + +```toml +[tool.fastapi] +entrypoint = "main:app" +``` + +该 `entrypoint` 会告诉 `fastapi` 命令按如下方式导入应用: + +```python +from main import app +``` + +如果你的代码结构如下: + +``` +. +├── backend +│   ├── main.py +│   ├── __init__.py +``` + +那么你可以将 `entrypoint` 设置为: + +```toml +[tool.fastapi] +entrypoint = "backend.main:app" +``` + +这等价于: + +```python +from backend.main import app +``` + +### `fastapi dev` 带路径 { #fastapi-dev-with-path } + +你也可以把文件路径传给 `fastapi dev` 命令,它会尝试推断要使用的 FastAPI 应用对象: + +```console +$ fastapi dev main.py +``` + +但这样每次调用 `fastapi` 命令时都需要记得传入正确的路径。 + +另外,其他工具可能无法找到它,例如 [VS Code 扩展](../editor-support.md) 或 [FastAPI Cloud](https://fastapicloud.com),因此推荐在 `pyproject.toml` 中使用 `entrypoint`。 + ### 部署你的应用(可选) { #deploy-your-app-optional } -你可以选择将 FastAPI 应用部署到 FastAPI Cloud,如果还没有,先去加入候补名单。🚀 +你可以选择将 FastAPI 应用部署到 [FastAPI Cloud](https://fastapicloud.com),如果还没有,先去加入候补名单。🚀 如果你已经拥有 **FastAPI Cloud** 账户(我们从候补名单邀请了你 😉),你可以用一条命令部署应用。 @@ -191,7 +240,7 @@ Deploying to FastAPI Cloud... `FastAPI` 是直接从 `Starlette` 继承的类。 -你可以通过 `FastAPI` 使用所有的 Starlette 的功能。 +你可以通过 `FastAPI` 使用所有的 [Starlette](https://www.starlette.dev/) 的功能。 /// @@ -273,7 +322,7 @@ https://example.com/items/foo * 请求路径为 `/` * 使用 get 操作 -/// info | `@decorator` Info +/// info | `@decorator` 信息 `@something` 语法在 Python 中被称为「装饰器」。 @@ -336,7 +385,7 @@ https://example.com/items/foo /// note -如果你不知道两者的区别,请查阅 [并发: *赶时间吗?*](../async.md#in-a-hurry){.internal-link target=_blank}。 +如果你不知道两者的区别,请查阅 [并发: *赶时间吗?*](../async.md#in-a-hurry)。 /// @@ -352,11 +401,11 @@ https://example.com/items/foo ### 步骤 6:部署 { #step-6-deploy-it } -用一条命令将你的应用部署到 **FastAPI Cloud**:`fastapi deploy`。🎉 +用一条命令将你的应用部署到 **[FastAPI Cloud](https://fastapicloud.com)**:`fastapi deploy`。🎉 #### 关于 FastAPI Cloud { #about-fastapi-cloud } -**FastAPI Cloud** 由 **FastAPI** 的作者和团队打造。 +**[FastAPI Cloud](https://fastapicloud.com)** 由 **FastAPI** 的作者和团队打造。 它以最小的投入简化了 **构建**、**部署** 和 **访问** API 的流程。 diff --git a/docs/zh/docs/tutorial/handling-errors.md b/docs/zh/docs/tutorial/handling-errors.md index 9782f3d225..f3a23fab0a 100644 --- a/docs/zh/docs/tutorial/handling-errors.md +++ b/docs/zh/docs/tutorial/handling-errors.md @@ -81,7 +81,7 @@ ## 安装自定义异常处理器 { #install-custom-exception-handlers } -可以使用与 Starlette 相同的异常处理工具添加自定义异常处理器。 +可以使用[与 Starlette 相同的异常处理工具](https://www.starlette.dev/exceptions/)添加自定义异常处理器。 假设有一个自定义异常 `UnicornException`(你自己或你使用的库可能会 `raise` 它)。 diff --git a/docs/zh/docs/tutorial/index.md b/docs/zh/docs/tutorial/index.md index 7934583023..8d6cbc7a6d 100644 --- a/docs/zh/docs/tutorial/index.md +++ b/docs/zh/docs/tutorial/index.md @@ -10,12 +10,12 @@ 所有代码片段都可以复制后直接使用(它们实际上是经过测试的 Python 文件)。 -要运行任何示例,请将代码复制到 `main.py` 文件中,然后使用以下命令启动 `fastapi dev`: +要运行任何示例,请将代码复制到 `main.py` 文件中,然后启动 `fastapi dev`:
```console -$ fastapi dev main.py +$ fastapi dev FastAPI Starting development server 🚀 @@ -62,7 +62,7 @@ $ fastapi dev @@ -76,7 +76,7 @@ $ pip install "fastapi[standard]" /// note | 注意 -当您使用 `pip install "fastapi[standard]"` 安装时,它会附带一些默认的可选标准依赖项,其中包括 `fastapi-cloud-cli`,它可以让您部署到 FastAPI Cloud。 +当您使用 `pip install "fastapi[standard]"` 安装时,它会附带一些默认的可选标准依赖项,其中包括 `fastapi-cloud-cli`,它可以让您部署到 [FastAPI Cloud](https://fastapicloud.com)。 如果您不想安装这些可选依赖,可以选择安装 `pip install fastapi`。 @@ -84,6 +84,12 @@ $ pip install "fastapi[standard]" /// +/// tip | 提示 + +FastAPI 提供了一个[VS Code 官方扩展](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode)(也支持 Cursor),包含众多功能,例如路径操作浏览器、路径操作搜索、测试中的 CodeLens 导航(从测试跳转到定义),以及从编辑器内进行 FastAPI Cloud 部署和查看日志。 + +/// + ## 进阶用户指南 { #advanced-user-guide } 在本**教程-用户指南**之后,您可以阅读**进阶用户指南**。 diff --git a/docs/zh/docs/tutorial/metadata.md b/docs/zh/docs/tutorial/metadata.md index 7ffaa070c5..b761f08886 100644 --- a/docs/zh/docs/tutorial/metadata.md +++ b/docs/zh/docs/tutorial/metadata.md @@ -14,7 +14,7 @@ | `version` | `string` | API 的版本。这是您自己的应用程序的版本,而不是 OpenAPI 的版本。例如 `2.5.0`。 | | `terms_of_service` | `str` | API 服务条款的 URL。如果提供,则必须是 URL。 | | `contact` | `dict` | 公开的 API 的联系信息。它可以包含多个字段。
contact 字段
参数类型描述
namestr联系人/组织的识别名称。
urlstr指向联系信息的 URL。必须采用 URL 格式。
emailstr联系人/组织的电子邮件地址。必须采用电子邮件地址的格式。
| -| `license_info` | `dict` | 公开的 API 的许可证信息。它可以包含多个字段。
license_info 字段
参数类型描述
namestr必须(如果设置了 license_info)。用于 API 的许可证名称。
identifierstrAPI 的 SPDX 许可证表达式。字段 identifier 与字段 url 互斥。自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。
urlstr用于 API 的许可证的 URL。必须采用 URL 格式。
| +| `license_info` | `dict` | 公开的 API 的许可证信息。它可以包含多个字段。
license_info 字段
参数类型描述
namestr必须(如果设置了 license_info)。用于 API 的许可证名称。
identifierstrAPI 的 [SPDX](https://spdx.org/licenses/) 许可证表达式。字段 identifier 与字段 url 互斥。自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。
urlstr用于 API 的许可证的 URL。必须采用 URL 格式。
| 你可以按如下方式设置它们: @@ -76,7 +76,7 @@ /// info | 信息 -阅读更多关于标签的信息[路径操作配置](path-operation-configuration.md#tags){.internal-link target=_blank}。 +阅读更多关于标签的信息[路径操作配置](path-operation-configuration.md#tags)。 /// diff --git a/docs/zh/docs/tutorial/middleware.md b/docs/zh/docs/tutorial/middleware.md index a211a63bdf..e7586132f2 100644 --- a/docs/zh/docs/tutorial/middleware.md +++ b/docs/zh/docs/tutorial/middleware.md @@ -15,7 +15,7 @@ 如果你有使用 `yield` 的依赖,依赖中的退出代码会在中间件之后运行。 -如果有任何后台任务(会在[后台任务](background-tasks.md){.internal-link target=_blank}一节中介绍,你稍后会看到),它们会在所有中间件之后运行。 +如果有任何后台任务(会在[后台任务](background-tasks.md)一节中介绍,你稍后会看到),它们会在所有中间件之后运行。 /// @@ -35,9 +35,9 @@ /// tip -请记住可以使用 `X-` 前缀添加专有自定义请求头。 +请记住可以[使用 `X-` 前缀](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)添加专有自定义请求头。 -但是如果你有希望让浏览器中的客户端可见的自定义请求头,你需要把它们加到你的 CORS 配置([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank})的 `expose_headers` 参数中,参见 Starlette 的 CORS 文档。 +但是如果你有希望让浏览器中的客户端可见的自定义请求头,你需要把它们加到你的 CORS 配置([CORS(跨域资源共享)](cors.md))的 `expose_headers` 参数中,参见 [Starlette 的 CORS 文档](https://www.starlette.dev/middleware/#corsmiddleware)。 /// @@ -61,7 +61,7 @@ /// tip -这里我们使用 `time.perf_counter()` 而不是 `time.time()`,因为在这类场景中它可能更精确。🤓 +这里我们使用 [`time.perf_counter()`](https://docs.python.org/3/library/time.html#time.perf_counter) 而不是 `time.time()`,因为在这类场景中它可能更精确。🤓 /// @@ -90,6 +90,6 @@ app.add_middleware(MiddlewareB) ## 其他中间件 { #other-middlewares } -你可以稍后在[高级用户指南:高级中间件](../advanced/middleware.md){.internal-link target=_blank}中阅读更多关于其他中间件的内容。 +你可以稍后在[高级用户指南:高级中间件](../advanced/middleware.md)中阅读更多关于其他中间件的内容。 你将在下一节中了解如何使用中间件处理 CORS。 diff --git a/docs/zh/docs/tutorial/path-operation-configuration.md b/docs/zh/docs/tutorial/path-operation-configuration.md index b3e4ba95c2..b9046a13be 100644 --- a/docs/zh/docs/tutorial/path-operation-configuration.md +++ b/docs/zh/docs/tutorial/path-operation-configuration.md @@ -58,7 +58,7 @@ OpenAPI 概图会自动添加标签,供 API 文档接口使用: 描述内容比较长且占用多行时,可以在函数的 docstring 中声明*路径操作*的描述,**FastAPI** 会从中读取。 -文档字符串支持 Markdown,能正确解析和显示 Markdown 的内容,但要注意文档字符串的缩进。 +文档字符串支持 [Markdown](https://en.wikipedia.org/wiki/Markdown),能正确解析和显示 Markdown 的内容,但要注意文档字符串的缩进。 {* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *} diff --git a/docs/zh/docs/tutorial/path-params-numeric-validations.md b/docs/zh/docs/tutorial/path-params-numeric-validations.md index 608aa69a1d..26b91c1d73 100644 --- a/docs/zh/docs/tutorial/path-params-numeric-validations.md +++ b/docs/zh/docs/tutorial/path-params-numeric-validations.md @@ -14,7 +14,7 @@ FastAPI 在 0.95.0 版本添加了对 `Annotated` 的支持(并开始推荐使 如果你使用的是更旧的版本,尝试使用 `Annotated` 会报错。 -请确保在使用 `Annotated` 之前,将 FastAPI 版本[升级](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}到至少 0.95.1。 +请确保在使用 `Annotated` 之前,将 FastAPI 版本[升级](../deployment/versions.md#upgrading-the-fastapi-versions)到至少 0.95.1。 /// @@ -122,7 +122,7 @@ Python 不会对这个 `*` 做任何事,但它会知道之后的所有参数 ## 总结 { #recap } -你能够以与[查询参数和字符串校验](query-params-str-validations.md){.internal-link target=_blank}相同的方式使用 `Query`、`Path`(以及其他你还没见过的类)声明元数据和字符串校验。 +你能够以与[查询参数和字符串校验](query-params-str-validations.md)相同的方式使用 `Query`、`Path`(以及其他你还没见过的类)声明元数据和字符串校验。 而且你还可以声明数值校验: @@ -139,7 +139,7 @@ Python 不会对这个 `*` 做任何事,但它会知道之后的所有参数 /// -/// note | 技术细节 +/// note | 注意 当你从 `fastapi` 导入 `Query`、`Path` 和其他对象时,它们实际上是函数。 diff --git a/docs/zh/docs/tutorial/path-params.md b/docs/zh/docs/tutorial/path-params.md index 06a9f1b442..df9210673c 100644 --- a/docs/zh/docs/tutorial/path-params.md +++ b/docs/zh/docs/tutorial/path-params.md @@ -6,7 +6,7 @@ 路径参数 `item_id` 的值会作为参数 `item_id` 传递给你的函数。 -运行示例并访问 http://127.0.0.1:8000/items/foo,可获得如下响应: +运行示例并访问 [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/items/foo),可获得如下响应: ```JSON {"item_id":"foo"} @@ -28,7 +28,7 @@ ## 数据转换 { #data-conversion } -运行示例并访问 http://127.0.0.1:8000/items/3,返回的响应如下: +运行示例并访问 [http://127.0.0.1:8000/items/3](http://127.0.0.1:8000/items/3),返回的响应如下: ```JSON {"item_id":3} @@ -44,7 +44,7 @@ ## 数据校验 { #data-validation } -通过浏览器访问 http://127.0.0.1:8000/items/foo,接收如下 HTTP 错误信息: +通过浏览器访问 [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/items/foo),接收如下 HTTP 错误信息: ```JSON { @@ -64,7 +64,7 @@ 这是因为路径参数 `item_id` 的值(`"foo"`)的类型不是 `int`。 -值的类型不是 `int` 而是浮点数(`float`)时也会显示同样的错误,比如: http://127.0.0.1:8000/items/4.2 +值的类型不是 `int` 而是浮点数(`float`)时也会显示同样的错误,比如: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) /// check | 检查 @@ -78,7 +78,7 @@ ## 文档 { #documentation } -访问 http://127.0.0.1:8000/docs,查看自动生成的交互式 API 文档: +访问 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs),查看自动生成的交互式 API 文档: @@ -92,9 +92,9 @@ ## 基于标准的好处,备选文档 { #standards-based-benefits-alternative-documentation } -**FastAPI** 使用 OpenAPI 生成概图,所以能兼容很多工具。 +**FastAPI** 使用 [OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md) 生成概图,所以能兼容很多工具。 -因此,**FastAPI** 还内置了 ReDoc 生成的备选 API 文档,可在此查看 http://127.0.0.1:8000/redoc: +因此,**FastAPI** 还内置了 ReDoc 生成的备选 API 文档,可在此查看 [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc): @@ -102,7 +102,7 @@ ## Pydantic { #pydantic } -FastAPI 充分地利用了 Pydantic 的优势,用它在后台校验数据。众所周知,Pydantic 擅长的就是数据校验。 +FastAPI 充分地利用了 [Pydantic](https://docs.pydantic.dev/) 的优势,用它在后台校验数据。众所周知,Pydantic 擅长的就是数据校验。 同样,`str`、`float`、`bool` 以及很多复合数据类型都可以使用类型声明。 diff --git a/docs/zh/docs/tutorial/query-params-str-validations.md b/docs/zh/docs/tutorial/query-params-str-validations.md index d41f302267..67a5b40008 100644 --- a/docs/zh/docs/tutorial/query-params-str-validations.md +++ b/docs/zh/docs/tutorial/query-params-str-validations.md @@ -35,13 +35,13 @@ FastAPI 在 0.95.0 版本中添加了对 `Annotated` 的支持(并开始推荐 如果你的版本更旧,使用 `Annotated` 会报错。 -在使用 `Annotated` 之前,请确保先[升级 FastAPI 版本](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}到至少 0.95.1。 +在使用 `Annotated` 之前,请确保先[升级 FastAPI 版本](../deployment/versions.md#upgrading-the-fastapi-versions)到至少 0.95.1。 /// ## 在 `q` 参数的类型中使用 `Annotated` { #use-annotated-in-the-type-for-the-q-parameter } -还记得我之前在[Python 类型简介](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}中说过可以用 `Annotated` 给参数添加元数据吗? +还记得我之前在[Python 类型简介](../python-types.md#type-hints-with-metadata-annotations)中说过可以用 `Annotated` 给参数添加元数据吗? 现在正是与 FastAPI 搭配使用它的时候。🚀 @@ -105,7 +105,7 @@ FastAPI 现在会: q: str | None = Query(default=None) ``` -……会让参数变成可选,默认值为 `None`,等同于: +...会让参数变成可选,默认值为 `None`,等同于: ```Python q: str | None = None @@ -133,7 +133,7 @@ q: str | None = Query(default=None, max_length=50) q: Annotated[str, Query(default="rick")] = "morty" ``` -……因为不清楚默认值应该是 `"rick"` 还是 `"morty"`。 +...因为不清楚默认值应该是 `"rick"` 还是 `"morty"`。 因此,你应该这样用(推荐): @@ -141,7 +141,7 @@ q: Annotated[str, Query(default="rick")] = "morty" q: Annotated[str, Query()] = "rick" ``` -……或者在旧代码库中你会见到: +...或者在旧代码库中你会见到: ```Python q: str = Query(default="rick") @@ -157,7 +157,7 @@ q: str = Query(default="rick") 当你不使用 `Annotated` 而是使用**(旧的)默认值风格**时,如果你在**其他地方**不通过 FastAPI 调用该函数,你必须**记得**给函数传参,否则得到的值会和预期不同(例如得到 `QueryInfo` 之类的对象而不是 `str`)。而你的编辑器不会报错,Python 也不会在调用时报错,只有在函数内部的操作出错时才会暴露问题。 -由于 `Annotated` 可以包含多个元数据标注,你甚至可以用同一个函数与其他工具配合,例如 Typer。🚀 +由于 `Annotated` 可以包含多个元数据标注,你甚至可以用同一个函数与其他工具配合,例如 [Typer](https://typer.tiangolo.com/)。🚀 ## 添加更多校验 { #add-more-validations } @@ -337,7 +337,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems 最接近的有效名称是 `item_query`。 -但你仍然需要它在 URL 中就是 `item-query`…… +但你仍然需要它在 URL 中就是 `item-query`... 这时可以用 `alias` 参数声明一个别名,FastAPI 会用该别名在 URL 中查找参数值: @@ -369,11 +369,11 @@ http://127.0.0.1:8000/items/?item-query=foobaritems 在这些情况下,你可以使用**自定义校验函数**,该函数会在正常校验之后应用(例如,在先校验值是 `str` 之后)。 -你可以在 `Annotated` 中使用 Pydantic 的 `AfterValidator` 来实现。 +你可以在 `Annotated` 中使用 [Pydantic 的 `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) 来实现。 /// tip | 提示 -Pydantic 还有 `BeforeValidator` 等。🤓 +Pydantic 还有 [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-before-validator) 等。🤓 /// @@ -421,7 +421,7 @@ Pydantic 还有 `python-multipart`。 +要接收上传的文件,请先安装 [`python-multipart`](https://github.com/Kludex/python-multipart)。 -请确保你创建一个[虚拟环境](../virtual-environments.md){.internal-link target=_blank}、激活它,然后安装,例如: +请确保你创建一个[虚拟环境](../virtual-environments.md)、激活它,然后安装,例如: ```console $ pip install python-multipart @@ -63,8 +63,8 @@ $ pip install python-multipart * 文件会先存储在内存中,直到达到最大上限,超过该上限后会写入磁盘。 * 因此,非常适合处理图像、视频、大型二进制等大文件,而不会占用所有内存。 * 你可以获取上传文件的元数据。 -* 它提供 file-like 的 `async` 接口。 -* 它暴露了一个实际的 Python `SpooledTemporaryFile` 对象,你可以直接传给期望「file-like」对象的其他库。 +* 它提供 [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) 的 `async` 接口。 +* 它暴露了一个实际的 Python [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) 对象,你可以直接传给期望「file-like」对象的其他库。 ### `UploadFile` { #uploadfile } @@ -72,7 +72,7 @@ $ pip install python-multipart * `filename`:上传的原始文件名字符串(`str`),例如 `myimage.jpg`。 * `content_type`:内容类型(MIME 类型 / 媒体类型)的字符串(`str`),例如 `image/jpeg`。 -* `file`:`SpooledTemporaryFile`(一个 file-like 对象)。这是实际的 Python 文件对象,你可以直接传递给其他期望「file-like」对象的函数或库。 +* `file`:[`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile)(一个 [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) 对象)。这是实际的 Python 文件对象,你可以直接传递给其他期望「file-like」对象的函数或库。 `UploadFile` 具有以下 `async` 方法。它们都会在底层调用对应的文件方法(使用内部的 `SpooledTemporaryFile`)。 @@ -97,13 +97,13 @@ contents = await myfile.read() contents = myfile.file.read() ``` -/// note | 注意 +/// note | `async` 技术细节 当你使用这些 `async` 方法时,**FastAPI** 会在线程池中运行相应的文件方法并等待其完成。 /// -/// note | 注意 +/// note | Starlette 技术细节 **FastAPI** 的 `UploadFile` 直接继承自 **Starlette** 的 `UploadFile`,但添加了一些必要的部分,使其与 **Pydantic** 以及 FastAPI 的其他部分兼容。 @@ -115,13 +115,13 @@ HTML 表单(`
`)向服务器发送数据的方式通常会对数 **FastAPI** 会确保从正确的位置读取这些数据,而不是从 JSON 中读取。 -/// note | 注意 +/// note | 技术细节 当不包含文件时,来自表单的数据通常使用「媒体类型」`application/x-www-form-urlencoded` 编码。 但当表单包含文件时,会编码为 `multipart/form-data`。如果你使用 `File`,**FastAPI** 会知道需要从请求体的正确位置获取文件。 -如果你想进一步了解这些编码和表单字段,请参阅 MDN 关于 POST 的 Web 文档。 +如果你想进一步了解这些编码和表单字段,请参阅 [MDN 关于 `POST` 的 Web 文档](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)。 /// @@ -135,13 +135,13 @@ HTML 表单(`
`)向服务器发送数据的方式通常会对数 ## 可选文件上传 { #optional-file-upload } -您可以通过使用标准类型注解并将 `None` 作为默认值的方式将一个文件参数设为可选: +你可以通过使用标准类型注解并将 `None` 作为默认值的方式将一个文件参数设为可选: {* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *} ## 带有额外元数据的 `UploadFile` { #uploadfile-with-additional-metadata } -您也可以将 `File()` 与 `UploadFile` 一起使用,例如,设置额外的元数据: +你也可以将 `File()` 与 `UploadFile` 一起使用,例如,设置额外的元数据: {* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} @@ -157,7 +157,7 @@ FastAPI 支持同时上传多个文件。 接收的也是含 `bytes` 或 `UploadFile` 的列表(`list`)。 -/// note | 注意 +/// note | 技术细节 也可以使用 `from starlette.responses import HTMLResponse`。 diff --git a/docs/zh/docs/tutorial/request-form-models.md b/docs/zh/docs/tutorial/request-form-models.md index 63759df086..ec52710a8f 100644 --- a/docs/zh/docs/tutorial/request-form-models.md +++ b/docs/zh/docs/tutorial/request-form-models.md @@ -4,9 +4,9 @@ /// info | 信息 -要使用表单,首先安装 `python-multipart`。 +要使用表单,首先安装 [`python-multipart`](https://github.com/Kludex/python-multipart)。 -确保你创建一个[虚拟环境](../virtual-environments.md){.internal-link target=_blank},激活它,然后再安装,例如: +确保你创建一个[虚拟环境](../virtual-environments.md),激活它,然后再安装,例如: ```console $ pip install python-multipart diff --git a/docs/zh/docs/tutorial/request-forms-and-files.md b/docs/zh/docs/tutorial/request-forms-and-files.md index 484fcd5d6d..8e092af0a8 100644 --- a/docs/zh/docs/tutorial/request-forms-and-files.md +++ b/docs/zh/docs/tutorial/request-forms-and-files.md @@ -4,9 +4,9 @@ FastAPI 支持同时使用 `File` 和 `Form` 定义文件和表单字段。 /// info | 信息 -接收上传的文件和/或表单数据,首先安装 `python-multipart`。 +接收上传的文件和/或表单数据,首先安装 [`python-multipart`](https://github.com/Kludex/python-multipart)。 -请先创建并激活一个[虚拟环境](../virtual-environments.md){.internal-link target=_blank},然后再安装,例如: +请先创建并激活一个[虚拟环境](../virtual-environments.md),然后再安装,例如: ```console $ pip install python-multipart diff --git a/docs/zh/docs/tutorial/request-forms.md b/docs/zh/docs/tutorial/request-forms.md index 1fc305a69c..ab82a181a2 100644 --- a/docs/zh/docs/tutorial/request-forms.md +++ b/docs/zh/docs/tutorial/request-forms.md @@ -4,9 +4,9 @@ /// info -要使用表单,首先安装 `python-multipart`。 +要使用表单,首先安装 [`python-multipart`](https://github.com/Kludex/python-multipart)。 -请先创建并激活一个[虚拟环境](../virtual-environments.md){.internal-link target=_blank},然后再进行安装,例如: +请先创建并激活一个[虚拟环境](../virtual-environments.md),然后再进行安装,例如: ```console $ pip install python-multipart @@ -28,7 +28,7 @@ $ pip install python-multipart 例如,在 OAuth2 规范的一种使用方式(称为“密码流”)中,要求将 `username` 和 `password` 作为表单字段发送。 -规范 要求这些字段必须精确命名为 `username` 和 `password`,并且作为表单字段发送,而不是 JSON。 +规范要求这些字段必须精确命名为 `username` 和 `password`,并且作为表单字段发送,而不是 JSON。 使用 `Form` 可以像使用 `Body`(以及 `Query`、`Path`、`Cookie`)一样声明相同的配置,包括校验、示例、别名(例如将 `username` 写成 `user-name`)等。 @@ -56,7 +56,7 @@ HTML 表单(`
`)向服务器发送数据时通常会对数据使 但当表单包含文件时,会编码为 `multipart/form-data`。你将在下一章阅读如何处理文件。 -如果你想了解更多关于这些编码和表单字段的信息,请参阅 MDN Web 文档的 POST。 +如果你想了解更多关于这些编码和表单字段的信息,请参阅 [MDN Web 文档的 `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)。 /// diff --git a/docs/zh/docs/tutorial/response-model.md b/docs/zh/docs/tutorial/response-model.md index df0afa66f8..9b4e0382e9 100644 --- a/docs/zh/docs/tutorial/response-model.md +++ b/docs/zh/docs/tutorial/response-model.md @@ -13,6 +13,7 @@ FastAPI 会使用这个返回类型来: * 在 OpenAPI 的*路径操作*中为响应添加**JSON Schema**。 * 它会被**自动文档**使用。 * 它也会被自动客户端代码生成工具使用。 +* 使用 Pydantic 将返回数据**序列化**为 JSON。Pydantic 使用**Rust**编写,因此会**快很多**。 但更重要的是: @@ -73,9 +74,9 @@ FastAPI 会使用这个 `response_model` 来完成数据文档、校验等,并 /// info | 信息 -要使用 `EmailStr`,首先安装 `email-validator`。 +要使用 `EmailStr`,首先安装 [`email-validator`](https://github.com/JoshData/python-email-validator)。 -请先创建并激活一个[虚拟环境](../virtual-environments.md){.internal-link target=_blank},然后安装,例如: +请先创建并激活一个[虚拟环境](../virtual-environments.md),然后安装,例如: ```console $ pip install email-validator @@ -181,7 +182,7 @@ FastAPI 在内部配合 Pydantic 做了多项处理,确保不会把类继承 ### 直接返回 Response { #return-a-response-directly } -最常见的情况是[直接返回 Response,详见进阶文档](../advanced/response-directly.md){.internal-link target=_blank}。 +最常见的情况是[直接返回 Response,详见进阶文档](../advanced/response-directly.md)。 {* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} @@ -257,7 +258,7 @@ FastAPI 在内部配合 Pydantic 做了多项处理,确保不会把类继承 * `response_model_exclude_defaults=True` * `response_model_exclude_none=True` -详见 Pydantic 文档中对 `exclude_defaults` 和 `exclude_none` 的说明。 +详见 [Pydantic 文档](https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict)中对 `exclude_defaults` 和 `exclude_none` 的说明。 /// diff --git a/docs/zh/docs/tutorial/response-status-code.md b/docs/zh/docs/tutorial/response-status-code.md index 266f919ba1..e57c0e5937 100644 --- a/docs/zh/docs/tutorial/response-status-code.md +++ b/docs/zh/docs/tutorial/response-status-code.md @@ -20,7 +20,7 @@ /// info | 信息 -`status_code` 还能接收 `IntEnum` 类型,比如 Python 的 `http.HTTPStatus`。 +`status_code` 还能接收 `IntEnum` 类型,比如 Python 的 [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus)。 /// @@ -66,7 +66,7 @@ FastAPI 可以进行识别,并生成表明无响应体的 OpenAPI 文档。 /// tip | 提示 -状态码及适用场景的详情,请参阅 MDN 的 HTTP 状态码文档。 +想了解每个状态码的更多信息以及适用场景,请参阅 [MDN 的 HTTP 状态码文档](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)。 /// @@ -98,4 +98,4 @@ FastAPI 可以进行识别,并生成表明无响应体的 OpenAPI 文档。 ## 更改默认状态码 { #changing-the-default } -[高级用户指南](../advanced/response-change-status-code.md){.internal-link target=_blank}中,将介绍如何返回与在此声明的默认状态码不同的状态码。 +稍后在[高级用户指南](../advanced/response-change-status-code.md)中,你将看到如何返回与此处声明的默认状态码不同的状态码。 diff --git a/docs/zh/docs/tutorial/schema-extra-example.md b/docs/zh/docs/tutorial/schema-extra-example.md index ec1fc29e55..482abd21de 100644 --- a/docs/zh/docs/tutorial/schema-extra-example.md +++ b/docs/zh/docs/tutorial/schema-extra-example.md @@ -12,7 +12,7 @@ 这些额外信息会原样添加到该模型输出的 JSON Schema 中,并会在 API 文档中使用。 -你可以使用属性 `model_config`,它接收一个 `dict`,详见 Pydantic 文档:配置。 +你可以使用属性 `model_config`,它接收一个 `dict`,详见 [Pydantic 文档:配置](https://docs.pydantic.dev/latest/api/config/)。 你可以设置 `"json_schema_extra"`,其值为一个 `dict`,包含你希望出现在生成 JSON Schema 中的任意附加数据,包括 `examples`。 @@ -145,12 +145,12 @@ OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)增加了对 `examples` 的支持 OpenAPI 还在规范的其他部分添加了 `example` 和 `examples` 字段: -- `Parameter Object`(规范中),被 FastAPI 的以下内容使用: +- [`Parameter Object`(规范中)](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-object),被 FastAPI 的以下内容使用: - `Path()` - `Query()` - `Header()` - `Cookie()` -- `Request Body Object` 中的 `content` 字段里的 `Media Type Object`(规范中),被 FastAPI 的以下内容使用: +- [`Request Body Object` 中的 `content` 字段里的 `Media Type Object`(规范中)](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#media-type-object),被 FastAPI 的以下内容使用: - `Body()` - `File()` - `Form()` @@ -163,7 +163,7 @@ OpenAPI 还在规范的其他部分添加了 `example` 和 `examples` 字段: ### JSON Schema 的 `examples` 字段 { #json-schemas-examples-field } -后来,JSON Schema 在新版本的规范中添加了 `examples` 字段。 +后来,JSON Schema 在新版本的规范中添加了 [`examples`](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5) 字段。 随后新的 OpenAPI 3.1.0 基于最新版本(JSON Schema 2020-12),其中包含了这个新的 `examples` 字段。 diff --git a/docs/zh/docs/tutorial/security/first-steps.md b/docs/zh/docs/tutorial/security/first-steps.md index 8b1aeb70b3..6cc91211a3 100644 --- a/docs/zh/docs/tutorial/security/first-steps.md +++ b/docs/zh/docs/tutorial/security/first-steps.md @@ -26,11 +26,11 @@ /// info | 信息 -当你使用命令 `pip install "fastapi[standard]"` 安装 **FastAPI** 时,`python-multipart` 包会自动安装。 +当你使用命令 `pip install "fastapi[standard]"` 安装 **FastAPI** 时,[`python-multipart`](https://github.com/Kludex/python-multipart) 包会自动安装。 但是,如果你使用 `pip install fastapi`,默认不会包含 `python-multipart` 包。 -如需手动安装,请先创建并激活[虚拟环境](../../virtual-environments.md){.internal-link target=_blank},然后执行: +如需手动安装,请先创建并激活[虚拟环境](../../virtual-environments.md),然后执行: ```console $ pip install python-multipart @@ -45,7 +45,7 @@ $ pip install python-multipart
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -54,7 +54,7 @@ $ fastapi dev main.py ## 查看 { #check-it } -打开交互式文档:http://127.0.0.1:8000/docs。 +打开交互式文档:[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 你会看到类似这样的界面: @@ -140,7 +140,7 @@ OAuth2 的设计目标是让后端或 API 与负责用户认证的服务器解 因为使用的是相对 URL,若你的 API 位于 `https://example.com/`,它将指向 `https://example.com/token`;若你的 API 位于 `https://example.com/api/v1/`,它将指向 `https://example.com/api/v1/token`。 -使用相对 URL 很重要,这能确保你的应用在诸如[使用代理](../../advanced/behind-a-proxy.md){.internal-link target=_blank}等高级用例中依然正常工作。 +使用相对 URL 很重要,这能确保你的应用在诸如[使用代理](../../advanced/behind-a-proxy.md)等高级用例中依然正常工作。 /// diff --git a/docs/zh/docs/tutorial/security/oauth2-jwt.md b/docs/zh/docs/tutorial/security/oauth2-jwt.md index b5ccfd3e3f..8a56137d37 100644 --- a/docs/zh/docs/tutorial/security/oauth2-jwt.md +++ b/docs/zh/docs/tutorial/security/oauth2-jwt.md @@ -24,13 +24,13 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4 一周后令牌过期,用户将不再被授权,需要重新登录以获取新令牌。而如果用户(或第三方)尝试修改令牌来更改过期时间,你也能发现,因为签名将不匹配。 -如果你想动手体验 JWT 令牌并了解它的工作方式,请访问 https://jwt.io。 +如果你想动手体验 JWT 令牌并了解它的工作方式,请访问 [https://jwt.io](https://jwt.io/)。 ## 安装 `PyJWT` { #install-pyjwt } 我们需要安装 `PyJWT`,以便在 Python 中生成和校验 JWT 令牌。 -请确保创建并激活一个[虚拟环境](../../virtual-environments.md){.internal-link target=_blank},然后安装 `pyjwt`: +请确保创建并激活一个[虚拟环境](../../virtual-environments.md),然后安装 `pyjwt`:
@@ -46,7 +46,7 @@ $ pip install pyjwt 如果你计划使用类似 RSA 或 ECDSA 的数字签名算法,你应该安装加密库依赖项 `pyjwt[crypto]`。 -可以在 PyJWT 安装文档中了解更多。 +可以在 [PyJWT 安装文档](https://pyjwt.readthedocs.io/en/latest/installation.html)中了解更多。 /// @@ -72,7 +72,7 @@ pwdlib 是一个用于处理密码哈希的优秀 Python 包。 推荐的算法是 “Argon2”。 -请确保创建并激活一个[虚拟环境](../../virtual-environments.md){.internal-link target=_blank},然后安装带 Argon2 的 pwdlib: +请确保创建并激活一个[虚拟环境](../../virtual-environments.md),然后安装带 Argon2 的 pwdlib:
@@ -200,7 +200,7 @@ JWT 除了用于识别用户并允许其直接在你的 API 上执行操作之 ## 检查 { #check-it } -运行服务器并打开文档:http://127.0.0.1:8000/docs。 +运行服务器并打开文档:[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 你会看到这样的用户界面: diff --git a/docs/zh/docs/tutorial/security/simple-oauth2.md b/docs/zh/docs/tutorial/security/simple-oauth2.md index 95f708ae6a..d8d5b561e0 100644 --- a/docs/zh/docs/tutorial/security/simple-oauth2.md +++ b/docs/zh/docs/tutorial/security/simple-oauth2.md @@ -146,7 +146,7 @@ UserInDB( /// info | 信息 -`user_dict` 的说明,详见[**更多模型**一章](../extra-models.md#about-user-in-dict){.internal-link target=_blank}。 +`user_dict` 的说明,详见[**更多模型**一章](../extra-models.md#about-user-in-dict)。 /// @@ -216,7 +216,7 @@ UserInDB( ## 实际效果 { #see-it-in-action } -打开 API 文档:http://127.0.0.1:8000/docs。 +打开交互式文档:[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 ### 身份验证 { #authenticate } diff --git a/docs/zh/docs/tutorial/sql-databases.md b/docs/zh/docs/tutorial/sql-databases.md index ef0b7c4601..9004983b10 100644 --- a/docs/zh/docs/tutorial/sql-databases.md +++ b/docs/zh/docs/tutorial/sql-databases.md @@ -2,9 +2,9 @@ **FastAPI** 并不要求你使用 SQL(关系型)数据库。你可以使用你想用的**任何数据库**。 -这里,我们来看一个使用 SQLModel 的示例。 +这里,我们来看一个使用 [SQLModel](https://sqlmodel.tiangolo.com/) 的示例。 -**SQLModel** 基于 SQLAlchemy 和 Pydantic 构建。它由 **FastAPI** 的同一作者制作,旨在完美匹配需要使用**SQL 数据库**的 FastAPI 应用程序。 +**SQLModel** 基于 [SQLAlchemy](https://www.sqlalchemy.org/) 和 Pydantic 构建。它由 **FastAPI** 的同一作者制作,旨在完美匹配需要使用**SQL 数据库**的 FastAPI 应用程序。 /// tip | 提示 @@ -26,15 +26,15 @@ /// tip | 提示 -有一个使用 **FastAPI** 和 **PostgreSQL** 的官方项目生成器,其中包括了前端和更多工具: https://github.com/fastapi/full-stack-fastapi-template +有一个使用 **FastAPI** 和 **PostgreSQL** 的官方项目生成器,其中包括了前端和更多工具: [https://github.com/fastapi/full-stack-fastapi-template](https://github.com/fastapi/full-stack-fastapi-template) /// -这是一个非常简单和简短的教程。如果你想了解一般的数据库、SQL 或更高级的功能,请查看 SQLModel 文档。 +这是一个非常简单和简短的教程。如果你想了解一般的数据库、SQL 或更高级的功能,请查看 [SQLModel 文档](https://sqlmodel.tiangolo.com/)。 ## 安装 `SQLModel` { #install-sqlmodel } -首先,确保你创建并激活了[虚拟环境](../virtual-environments.md){.internal-link target=_blank},然后安装 `sqlmodel`: +首先,确保你创建并激活了[虚拟环境](../virtual-environments.md),然后安装 `sqlmodel`:
@@ -65,7 +65,7 @@ $ pip install sqlmodel * `Field(primary_key=True)` 会告诉 SQLModel `id` 是 SQL 数据库中的**主键**(你可以在 SQLModel 文档中了解更多关于 SQL 主键的信息)。 - **注意:** 我们为主键字段使用 `int | None`,这样在 Python 代码中我们可以在没有 `id`(`id=None`)的情况下创建对象,并假定数据库在保存时会生成它。SQLModel 会理解数据库会提供 `id`,并在数据库模式中将该列定义为非空的 `INTEGER`。详见 SQLModel 关于主键的文档。 + **注意:** 我们为主键字段使用 `int | None`,这样在 Python 代码中我们可以在没有 `id`(`id=None`)的情况下创建对象,并假定数据库在保存时会生成它。SQLModel 会理解数据库会提供 `id`,并在数据库模式中将该列定义为非空的 `INTEGER`。详见 [SQLModel 关于主键的文档](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id)。 * `Field(index=True)` 会告诉 SQLModel 应该为此列创建一个 **SQL 索引**,这样在读取按此列过滤的数据时,程序能在数据库中进行更快的查找。 @@ -111,7 +111,7 @@ SQLModel 的 `engine`(实际上它是一个 SQLAlchemy 的 `engine`)是用 /// tip | 提示 -SQLModel 将会拥有封装 Alembic 的迁移工具,但目前你可以直接使用 Alembic。 +SQLModel 将会拥有封装 Alembic 的迁移工具,但目前你可以直接使用 [Alembic](https://alembic.sqlalchemy.org/en/latest/)。 /// @@ -152,7 +152,7 @@ SQLModel 将会拥有封装 Alembic 的迁移工具,但目前你可以直接
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -337,7 +337,7 @@ $ fastapi dev main.py
```console -$ fastapi dev main.py +$ fastapi dev INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -352,6 +352,6 @@ $ fastapi dev main.py ## 总结 { #recap } -你可以使用 **SQLModel** 与 SQL 数据库进行交互,并通过*数据模型*和*表模型*简化代码。 +你可以使用 [**SQLModel**](https://sqlmodel.tiangolo.com/) 与 SQL 数据库进行交互,并通过*数据模型*和*表模型*简化代码。 -你可以在 **SQLModel** 文档中学习到更多内容,其中有一个更详细的将 SQLModel 与 **FastAPI** 一起使用的迷你教程。🚀 +你可以在 **SQLModel** 文档中学习到更多内容,其中有一个更详细的[将 SQLModel 与 **FastAPI** 一起使用的迷你教程](https://sqlmodel.tiangolo.com/tutorial/fastapi/)。🚀 diff --git a/docs/zh/docs/tutorial/static-files.md b/docs/zh/docs/tutorial/static-files.md index 1f4ebae9ab..65262bdb40 100644 --- a/docs/zh/docs/tutorial/static-files.md +++ b/docs/zh/docs/tutorial/static-files.md @@ -23,7 +23,7 @@ 这与使用 `APIRouter` 不同,因为挂载的应用是完全独立的。主应用的 OpenAPI 和文档不会包含已挂载应用的任何内容,等等。 -你可以在[高级用户指南](../advanced/index.md){.internal-link target=_blank}中了解更多。 +你可以在[高级用户指南](../advanced/index.md)中了解更多。 ## 细节 { #details } @@ -37,4 +37,4 @@ ## 更多信息 { #more-info } -更多细节和选项请查阅 Starlette 的静态文件文档。 +更多细节和选项请查阅 [Starlette 的静态文件文档](https://www.starlette.dev/staticfiles/)。 diff --git a/docs/zh/docs/tutorial/testing.md b/docs/zh/docs/tutorial/testing.md index 7eb32f19e6..6607a12391 100644 --- a/docs/zh/docs/tutorial/testing.md +++ b/docs/zh/docs/tutorial/testing.md @@ -1,18 +1,18 @@ # 测试 { #testing } -感谢 Starlette,测试**FastAPI** 应用轻松又愉快。 +感谢 [Starlette](https://www.starlette.dev/testclient/),测试**FastAPI** 应用轻松又愉快。 -它基于 HTTPX, 而HTTPX又是基于Requests设计的,所以很相似且易懂。 +它基于 [HTTPX](https://www.python-httpx.org),而HTTPX又是基于Requests设计的,所以很相似且易懂。 -有了它,你可以直接与**FastAPI**一起使用 pytest。 +有了它,你可以直接与**FastAPI**一起使用 [pytest](https://docs.pytest.org/)。 ## 使用 `TestClient` { #using-testclient } /// info | 信息 -要使用 `TestClient`,先要安装 `httpx`。 +要使用 `TestClient`,先要安装 [`httpx`](https://www.python-httpx.org)。 -确保你创建并激活一个[虚拟环境](../virtual-environments.md){.internal-link target=_blank},然后再安装,例如: +确保你创建并激活一个[虚拟环境](../virtual-environments.md),然后再安装,例如: ```console $ pip install httpx @@ -52,7 +52,7 @@ $ pip install httpx /// tip | 提示 -除了发送请求之外,如果你还想测试时在FastAPI应用中调用 `async` 函数(例如异步数据库函数), 可以在高级教程中看下 [Async Tests](../advanced/async-tests.md){.internal-link target=_blank} 。 +除了发送请求之外,如果你还想测试时在FastAPI应用中调用 `async` 函数(例如异步数据库函数), 可以在高级教程中看下 [Async Tests](../advanced/async-tests.md) 。 /// @@ -64,7 +64,7 @@ $ pip install httpx ### **FastAPI** app 文件 { #fastapi-app-file } -假设你有一个像 [更大的应用](bigger-applications.md){.internal-link target=_blank} 中所描述的文件结构: +假设你有一个像[更大的应用](bigger-applications.md)中所描述的文件结构: ``` . @@ -112,7 +112,7 @@ $ pip install httpx │   └── test_main.py ``` -假设现在包含**FastAPI** app的文件 `main.py` 有些其他**路径操作**。 +假设现在包含**FastAPI** app的文件 `main.py` 有些其他**路径操作**。 有个 `GET` 操作会返回错误。 @@ -128,7 +128,7 @@ $ pip install httpx {* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} -每当你需要客户端在请求中传递信息,但你不知道如何传递时,你可以通过搜索(谷歌)如何用 `httpx`做,或者是用 `requests` 做,毕竟HTTPX的设计是基于Requests的设计的。 +每当你需要客户端在请求中传递信息,但你不知道如何传递时,你可以通过搜索(谷歌)如何用 `httpx` 做,或者是用 `requests` 做,毕竟HTTPX的设计是基于Requests的设计的。 接着只需在测试中同样操作。 @@ -140,13 +140,13 @@ $ pip install httpx * 要发送 *headers*,传 `dict` 给 `headers` 参数。 * 对于 *cookies*,传 `dict` 给 `cookies` 参数。 -关于如何传数据给后端的更多信息 (使用`httpx` 或 `TestClient`),请查阅 HTTPX 文档. +关于如何传数据给后端的更多信息(使用 `httpx` 或 `TestClient`),请查阅 [HTTPX 文档](https://www.python-httpx.org)。 /// info | 信息 注意 `TestClient` 接收可以被转化为JSON的数据,而不是Pydantic模型。 -如果你在测试中有一个Pydantic模型,并且你想在测试时发送它的数据给应用,你可以使用在[JSON Compatible Encoder](encoder.md){.internal-link target=_blank}介绍的`jsonable_encoder` 。 +如果你在测试中有一个Pydantic模型,并且你想在测试时发送它的数据给应用,你可以使用在[JSON Compatible Encoder](encoder.md)介绍的`jsonable_encoder` 。 /// @@ -154,7 +154,7 @@ $ pip install httpx 之后,你只需要安装 `pytest`。 -确保你创建并激活一个[虚拟环境](../virtual-environments.md){.internal-link target=_blank},然后再安装,例如: +确保你创建并激活一个[虚拟环境](../virtual-environments.md),然后再安装,例如:
diff --git a/docs/zh/docs/virtual-environments.md b/docs/zh/docs/virtual-environments.md index 60fb9e23f6..14ee538639 100644 --- a/docs/zh/docs/virtual-environments.md +++ b/docs/zh/docs/virtual-environments.md @@ -22,7 +22,7 @@ 这个页面将教你如何使用**虚拟环境**以及了解它们的工作原理。 -如果你计划使用一个**可以为你管理一切的工具**(包括安装 Python),试试 uv。 +如果你计划使用一个**可以为你管理一切的工具**(包括安装 Python),试试 [uv](https://github.com/astral-sh/uv)。 /// @@ -86,7 +86,7 @@ $ python -m venv .venv //// tab | `uv` -如果你安装了 `uv`,你也可以使用它来创建一个虚拟环境。 +如果你安装了 [`uv`](https://github.com/astral-sh/uv),你也可以使用它来创建一个虚拟环境。
@@ -150,7 +150,7 @@ $ .venv\Scripts\Activate.ps1 //// tab | Windows Bash -或者,如果你在 Windows 上使用 Bash(例如 Git Bash): +或者,如果你在 Windows 上使用 Bash(例如 [Git Bash](https://gitforwindows.org/)):
@@ -216,7 +216,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python /// tip | 提示 -如果你使用 `uv` 来安装内容,而不是 `pip`,那么你就不需要升级 `pip`。😎 +如果你使用 [`uv`](https://github.com/astral-sh/uv) 来安装内容,而不是 `pip`,那么你就不需要升级 `pip`。😎 /// @@ -268,7 +268,7 @@ $ python -m ensurepip --upgrade /// tip | 提示 -如果你使用 `uv` 来创建虚拟环境,它会自动为你完成这个操作,你可以跳过这一步。😎 +如果你使用 [`uv`](https://github.com/astral-sh/uv) 来创建虚拟环境,它会自动为你完成这个操作,你可以跳过这一步。😎 /// @@ -340,7 +340,7 @@ $ pip install "fastapi[standard]" //// tab | `uv` -如果你有 `uv`: +如果你有 [`uv`](https://github.com/astral-sh/uv):
@@ -372,7 +372,7 @@ $ pip install -r requirements.txt //// tab | `uv` -如果你有 `uv`: +如果你有 [`uv`](https://github.com/astral-sh/uv):
@@ -416,8 +416,8 @@ Hello World 例如: -* VS Code -* PyCharm +* [VS Code](https://code.visualstudio.com/docs/python/environments#_select-and-activate-an-environment) +* [PyCharm](https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html) /// tip | 提示 @@ -455,7 +455,7 @@ $ deactivate ## 为什么要使用虚拟环境 { #why-virtual-environments } -你需要安装 Python 才能使用 FastAPI。 +你需要安装 [Python](https://www.python.org/) 才能使用 FastAPI。 之后,你需要**安装** FastAPI 和你想要使用的任何其他**软件包**。 @@ -564,7 +564,7 @@ $ pip install "fastapi[standard]"
-这将会从 PyPI 下载一个压缩文件,其中包含 FastAPI 代码。 +这将会从 [PyPI](https://pypi.org/project/fastapi/) 下载一个压缩文件,其中包含 FastAPI 代码。 它还会**下载** FastAPI 依赖的其他软件包的文件。 @@ -627,7 +627,7 @@ $ .venv\Scripts\Activate.ps1 //// tab | Windows Bash -或者如果你在 Windows 上使用 Bash(例如 Git Bash): +或者如果你在 Windows 上使用 Bash(例如 [Git Bash](https://gitforwindows.org/)):
@@ -639,13 +639,13 @@ $ source .venv/Scripts/activate //// -这个命令会创建或修改一些[环境变量](environment-variables.md){.internal-link target=_blank},这些环境变量将在接下来的命令中可用。 +这个命令会创建或修改一些[环境变量](environment-variables.md),这些环境变量将在接下来的命令中可用。 其中之一是 `PATH` 变量。 /// tip | 提示 -你可以在 [环境变量](environment-variables.md#path-environment-variable){.internal-link target=_blank} 部分了解更多关于 `PATH` 环境变量的内容。 +你可以在 [环境变量](environment-variables.md#path-environment-variable) 部分了解更多关于 `PATH` 环境变量的内容。 /// @@ -846,7 +846,7 @@ I solemnly swear 🐺 有许多**替代方案**来管理虚拟环境、包依赖(requirements)、工程。 -一旦你准备好并想要使用一个工具来**管理整个工程**、包依赖、虚拟环境等,建议你尝试 uv。 +一旦你准备好并想要使用一个工具来**管理整个工程**、包依赖、虚拟环境等,建议你尝试 [uv](https://github.com/astral-sh/uv)。 `uv` 可以做很多事情,它可以: From 64feaec80244578bbdabe51e866bcfad1df8b708 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Mar 2026 17:07:25 +0000 Subject: [PATCH 18/69] =?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 3d868e034e..6278bcc959 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Translations +* 🌐 Update translations for zh (update-outdated). PR [#15177](https://github.com/fastapi/fastapi/pull/15177) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh-hant (update-outdated). PR [#15178](https://github.com/fastapi/fastapi/pull/15178) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh-hant (add-missing). PR [#15176](https://github.com/fastapi/fastapi/pull/15176) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (add-missing). PR [#15175](https://github.com/fastapi/fastapi/pull/15175) by [@tiangolo](https://github.com/tiangolo). From aeb9f4bb854d030803e2d13cdb64dd0bc5843f00 Mon Sep 17 00:00:00 2001 From: Sofie Van Landeghem Date: Mon, 23 Mar 2026 13:36:49 +0100 Subject: [PATCH 19/69] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Increase=20lower=20b?= =?UTF-8?q?ound=20to=20`pydantic=20>=3D2.9.0.`=20and=20fix=20the=20test=20?= =?UTF-8?q?suite=20(#15139)?= 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> --- .github/workflows/test.yml | 3 ++ pyproject.toml | 4 +- tests/test_schema_compat_pydantic_v2.py | 67 ++++++++++++++++++------- tests/test_union_body_discriminator.py | 59 ++++++++++++++++------ uv.lock | 4 +- 5 files changed, 100 insertions(+), 37 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2e39633a0c..e852e0f25d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -102,6 +102,9 @@ jobs: uv.lock - name: Install Dependencies run: uv sync --no-dev --group tests --extra all + - name: Ensure that we have the lowest supported Pydantic version + if: matrix.uv-resolution == 'lowest-direct' + run: uv pip install "pydantic==2.9.0" - name: Install Starlette from source if: matrix.starlette-src == 'starlette-git' run: uv pip install "git+https://github.com/Kludex/starlette@main" diff --git a/pyproject.toml b/pyproject.toml index 73d3929292..612d8a0d8a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ classifiers = [ ] dependencies = [ "starlette>=0.46.0", - "pydantic>=2.7.0", + "pydantic>=2.9.0", "typing-extensions>=4.8.0", "typing-inspection>=0.4.2", "annotated-doc>=0.0.2", @@ -156,7 +156,7 @@ docs-tests = [ ] github-actions = [ "httpx >=0.27.0,<1.0.0", - "pydantic >=2.5.3,<3.0.0", + "pydantic >=2.9.0,<3.0.0", "pydantic-settings >=2.1.0,<3.0.0", "pygithub >=2.3.0,<3.0.0", "pyyaml >=5.3.1,<7.0.0", diff --git a/tests/test_schema_compat_pydantic_v2.py b/tests/test_schema_compat_pydantic_v2.py index 737687f256..7612c6ab5b 100644 --- a/tests/test_schema_compat_pydantic_v2.py +++ b/tests/test_schema_compat_pydantic_v2.py @@ -1,4 +1,5 @@ import pytest +from dirty_equals import IsOneOf from fastapi import FastAPI from fastapi.testclient import TestClient from inline_snapshot import snapshot @@ -63,28 +64,58 @@ def test_openapi_schema(client: TestClient): } }, "components": { - "schemas": { - "PlatformRole": { - "type": "string", - "enum": ["admin", "user"], - "title": "PlatformRole", + "schemas": IsOneOf( + # Pydantic >= 2.11: no top-level OtherRole + { + "PlatformRole": { + "type": "string", + "enum": ["admin", "user"], + "title": "PlatformRole", + }, + "User": { + "properties": { + "username": {"type": "string", "title": "Username"}, + "role": { + "anyOf": [ + {"$ref": "#/components/schemas/PlatformRole"}, + {"enum": [], "title": "OtherRole"}, + ], + "title": "Role", + }, + }, + "type": "object", + "required": ["username", "role"], + "title": "User", + }, }, - "User": { - "properties": { - "username": {"type": "string", "title": "Username"}, - "role": { - "anyOf": [ - {"$ref": "#/components/schemas/PlatformRole"}, - {"enum": [], "title": "OtherRole"}, - ], - "title": "Role", + # Pydantic < 2.11: adds a top-level OtherRole schema + { + "OtherRole": { + "enum": [], + "title": "OtherRole", + }, + "PlatformRole": { + "type": "string", + "enum": ["admin", "user"], + "title": "PlatformRole", + }, + "User": { + "properties": { + "username": {"type": "string", "title": "Username"}, + "role": { + "anyOf": [ + {"$ref": "#/components/schemas/PlatformRole"}, + {"enum": [], "title": "OtherRole"}, + ], + "title": "Role", + }, }, + "type": "object", + "required": ["username", "role"], + "title": "User", }, - "type": "object", - "required": ["username", "role"], - "title": "User", }, - } + ) }, } ) diff --git a/tests/test_union_body_discriminator.py b/tests/test_union_body_discriminator.py index 1b682c7751..53350abc06 100644 --- a/tests/test_union_body_discriminator.py +++ b/tests/test_union_body_discriminator.py @@ -1,5 +1,6 @@ from typing import Annotated, Any, Literal +from dirty_equals import IsOneOf from fastapi import FastAPI from fastapi.testclient import TestClient from inline_snapshot import snapshot @@ -88,11 +89,19 @@ def test_discriminator_pydantic_v2() -> None: "description": "Successful Response", "content": { "application/json": { - "schema": { - "type": "object", - "additionalProperties": True, - "title": "Response Save Union Body Discriminator Items Post", - } + "schema": IsOneOf( + # Pydantic < 2.11: no additionalProperties + { + "type": "object", + "title": "Response Save Union Body Discriminator Items Post", + }, + # Pydantic >= 2.11: has additionalProperties + { + "type": "object", + "additionalProperties": True, + "title": "Response Save Union Body Discriminator Items Post", + }, + ) } }, }, @@ -114,11 +123,21 @@ def test_discriminator_pydantic_v2() -> None: "schemas": { "FirstItem": { "properties": { - "value": { - "type": "string", - "const": "first", - "title": "Value", - }, + "value": IsOneOf( + # Pydantic >= 2.10: const only + { + "type": "string", + "const": "first", + "title": "Value", + }, + # Pydantic 2.9: const + enum + { + "type": "string", + "const": "first", + "enum": ["first"], + "title": "Value", + }, + ), "price": {"type": "integer", "title": "Price"}, }, "type": "object", @@ -140,11 +159,21 @@ def test_discriminator_pydantic_v2() -> None: }, "OtherItem": { "properties": { - "value": { - "type": "string", - "const": "other", - "title": "Value", - }, + "value": IsOneOf( + # Pydantic >= 2.10.0: const only + { + "type": "string", + "const": "other", + "title": "Value", + }, + # Pydantic 2.9.x: const + enum + { + "type": "string", + "const": "other", + "enum": ["other"], + "title": "Value", + }, + ), "price": {"type": "number", "title": "Price"}, }, "type": "object", diff --git a/uv.lock b/uv.lock index 096b0a361c..90e9b4e462 100644 --- a/uv.lock +++ b/uv.lock @@ -1252,7 +1252,7 @@ requires-dist = [ { name = "jinja2", marker = "extra == 'all'", specifier = ">=3.1.5" }, { name = "jinja2", marker = "extra == 'standard'", specifier = ">=3.1.5" }, { name = "jinja2", marker = "extra == 'standard-no-fastapi-cloud-cli'", specifier = ">=3.1.5" }, - { name = "pydantic", specifier = ">=2.7.0" }, + { name = "pydantic", specifier = ">=2.9.0" }, { name = "pydantic-extra-types", marker = "extra == 'all'", specifier = ">=2.0.0" }, { name = "pydantic-extra-types", marker = "extra == 'standard'", specifier = ">=2.0.0" }, { name = "pydantic-extra-types", marker = "extra == 'standard-no-fastapi-cloud-cli'", specifier = ">=2.0.0" }, @@ -1350,7 +1350,7 @@ docs-tests = [ ] github-actions = [ { name = "httpx", specifier = ">=0.27.0,<1.0.0" }, - { name = "pydantic", specifier = ">=2.5.3,<3.0.0" }, + { name = "pydantic", specifier = ">=2.9.0,<3.0.0" }, { name = "pydantic-settings", specifier = ">=2.1.0,<3.0.0" }, { name = "pygithub", specifier = ">=2.3.0,<3.0.0" }, { name = "pyyaml", specifier = ">=5.3.1,<7.0.0" }, From cbd64b09a32681d3b0ea097608bc62eb0d1587e0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Mar 2026 12:37:17 +0000 Subject: [PATCH 20/69] =?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 6278bcc959..e832bdbe5b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Upgrades + +* ⬆️ Increase lower bound to `pydantic >=2.9.0.` and fix the test suite. PR [#15139](https://github.com/fastapi/fastapi/pull/15139) by [@svlandeg](https://github.com/svlandeg). + ### Docs * 📝 Fix duplicated words in docstrings. PR [#15116](https://github.com/fastapi/fastapi/pull/15116) by [@AhsanSheraz](https://github.com/AhsanSheraz). From 0227991a01e61bf5cdd93cc00e9e243f52b47a4a Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Mon, 23 Mar 2026 14:51:24 +0100 Subject: [PATCH 21/69] =?UTF-8?q?=F0=9F=94=A8=20Exclude=20spam=20comments?= =?UTF-8?q?=20from=20statistics=20in=20`scripts/people.py`=20(#15088)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/people.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/scripts/people.py b/scripts/people.py index 2e84fcc455..5718d65da9 100644 --- a/scripts/people.py +++ b/scripts/people.py @@ -7,12 +7,12 @@ from collections.abc import Container from datetime import datetime, timedelta, timezone from math import ceil from pathlib import Path -from typing import Any +from typing import Annotated, Any import httpx import yaml from github import Github -from pydantic import BaseModel, SecretStr +from pydantic import BaseModel, BeforeValidator, SecretStr from pydantic_settings import BaseSettings github_graphql_url = "https://api.github.com/graphql" @@ -21,6 +21,8 @@ questions_category_id = "DIC_kwDOCZduT84B6E2a" POINTS_PER_MINUTE_LIMIT = 84 # 5000 points per hour +MINIMIZED_COMMENTS_REASONS_TO_EXCLUDE = {"abuse", "off-topic", "duplicate", "spam"} + class RateLimiter: def __init__(self) -> None: @@ -102,8 +104,10 @@ query Q($after: String, $category_id: ID) { avatarUrl url } + minimizedReason } } + minimizedReason } } } @@ -118,6 +122,10 @@ query Q($after: String, $category_id: ID) { } """ +LowerStr = Annotated[ + str, BeforeValidator(lambda v: v.lower() if isinstance(v, str) else v) +] + class Author(BaseModel): login: str @@ -128,6 +136,7 @@ class Author(BaseModel): class CommentsNode(BaseModel): createdAt: datetime author: Author | None = None + minimizedReason: LowerStr | None = None class Replies(BaseModel): @@ -136,6 +145,7 @@ class Replies(BaseModel): class DiscussionsCommentsNode(CommentsNode): + minimizedReason: LowerStr | None = None replies: Replies @@ -278,7 +288,10 @@ def get_discussions_experts( discussion_author_name = discussion.author.login discussion_commentors: dict[str, datetime] = {} for comment in discussion.comments.nodes: - if comment.author: + if ( + comment.minimizedReason not in MINIMIZED_COMMENTS_REASONS_TO_EXCLUDE + and comment.author + ): authors[comment.author.login] = comment.author if comment.author.login != discussion_author_name: author_time = discussion_commentors.get( @@ -288,7 +301,10 @@ def get_discussions_experts( author_time, comment.createdAt ) for reply in comment.replies.nodes: - if reply.author: + if ( + reply.minimizedReason not in MINIMIZED_COMMENTS_REASONS_TO_EXCLUDE + and reply.author + ): authors[reply.author.login] = reply.author if reply.author.login != discussion_author_name: author_time = discussion_commentors.get( From fce9460f865928eb7d0393d8809bbc472e0c21cd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Mar 2026 13:51:55 +0000 Subject: [PATCH 22/69] =?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 e832bdbe5b..53ca17db82 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -48,6 +48,7 @@ hide: ### Internal +* 🔨 Exclude spam comments from statistics in `scripts/people.py`. PR [#15088](https://github.com/fastapi/fastapi/pull/15088) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ Bump authlib from 1.6.7 to 1.6.9. PR [#15128](https://github.com/fastapi/fastapi/pull/15128) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pyasn1 from 0.6.2 to 0.6.3. PR [#15143](https://github.com/fastapi/fastapi/pull/15143) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump ujson from 5.11.0 to 5.12.0. PR [#15150](https://github.com/fastapi/fastapi/pull/15150) by [@dependabot[bot]](https://github.com/apps/dependabot). From fd9e192cf4fae399c0d51dd23e2a137052eb6087 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Mon, 23 Mar 2026 14:56:46 +0100 Subject: [PATCH 23/69] =?UTF-8?q?=F0=9F=92=84=20Fix=20code=20blocks=20in?= =?UTF-8?q?=20reference=20docs=20overflowing=20table=20width=20(#15094)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/css/custom.css | 6 ++++++ docs/en/mkdocs.yml | 1 + 2 files changed, 7 insertions(+) diff --git a/docs/en/docs/css/custom.css b/docs/en/docs/css/custom.css index e207197c75..bbfd49b55e 100644 --- a/docs/en/docs/css/custom.css +++ b/docs/en/docs/css/custom.css @@ -254,6 +254,12 @@ Inspired by Termynal's CSS tricks with modifications box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; } +.doc-param-details .highlight { + overflow-x: auto; + width: 0; + min-width: 100%; +} + .md-typeset dfn { border-bottom: .05rem dotted var(--md-default-fg-color--light); cursor: help; diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index 0db3e7a95b..4614194981 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -279,6 +279,7 @@ markdown_extensions: pymdownx.caret: null pymdownx.highlight: line_spans: __span + linenums_style: pymdownx-inline pymdownx.inlinehilite: null pymdownx.keys: null pymdownx.mark: null From d0a6f208c5cb5daaa1de5ea5187729e3789d1dce Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Mar 2026 13:57:14 +0000 Subject: [PATCH 24/69] =?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 53ca17db82..bb3c0f117e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Docs +* 💄 Fix code blocks in reference docs overflowing table width. PR [#15094](https://github.com/fastapi/fastapi/pull/15094) by [@YuriiMotov](https://github.com/YuriiMotov). * 📝 Fix duplicated words in docstrings. PR [#15116](https://github.com/fastapi/fastapi/pull/15116) by [@AhsanSheraz](https://github.com/AhsanSheraz). * 📝 Add docs for `pyproject.toml` with `entrypoint`. PR [#15075](https://github.com/fastapi/fastapi/pull/15075) by [@tiangolo](https://github.com/tiangolo). * 📝 Update links in docs to no longer use the classes external-link and internal-link. PR [#15061](https://github.com/fastapi/fastapi/pull/15061) by [@tiangolo](https://github.com/tiangolo). From ea6e287eb398afe6a82c3ef71780e8451813f674 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Mon, 23 Mar 2026 14:59:26 +0100 Subject: [PATCH 25/69] =?UTF-8?q?=F0=9F=93=9D=20Update=20docs=20for=20cont?= =?UTF-8?q?ributors=20and=20team=20members=20regarding=20translation=20PRs?= =?UTF-8?q?=20(#15200)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/contributing.md | 8 +++++++- docs/en/docs/management-tasks.md | 9 ++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/docs/en/docs/contributing.md b/docs/en/docs/contributing.md index 07031a235a..fe7318f6cd 100644 --- a/docs/en/docs/contributing.md +++ b/docs/en/docs/contributing.md @@ -191,7 +191,11 @@ If you see mistakes in your language, you can make suggestions to the prompt in #### Reviewing Translation PRs -You can also check the currently [existing pull requests](https://github.com/fastapi/fastapi/pulls) for your language. You can filter the pull requests by the ones with the label for your language. For example, for Spanish, the label is [`lang-es`](https://github.com/fastapi/fastapi/pulls?q=is%3Aopen+sort%3Aupdated-desc+label%3Alang-es+label%3Aawaiting-review). +We don’t require approval from native speakers for translation PRs generated automatically by our translation workflow. However, you can still review them and suggest improvements to the LLM prompt for that language to make the future translations better. + +You can check the currently [existing pull requests](https://github.com/fastapi/fastapi/pulls) for your language. You can filter the pull requests by the ones with the label for your language. For example, for Spanish, the label is [`lang-es`](https://github.com/fastapi/fastapi/pulls?q=is%3Aopen+sort%3Aupdated-desc+label%3Alang-es+label%3Aawaiting-review). + +You can also review already merged translation PRs. To do this, go to the [closed pull requests](https://github.com/fastapi/fastapi/pulls?q=is%3Apr+is%3Aclosed) and filter by your language label. For example, for Spanish, you can use [`lang-es`](https://github.com/fastapi/fastapi/pulls?q=is%3Apr+is%3Aclosed+label%3Alang-es). When reviewing a pull request, it's better not to suggest changes in the same pull request, because it is LLM generated, and it won't be possible to make sure that small individual changes are replicated in other similar sections, or that they are preserved when translating the same content again. @@ -203,6 +207,8 @@ Check the docs about [adding a pull request review](https://help.github.com/en/g /// +PRs with suggestions to the language-specific LLM prompt require approval from at least one native speaker. Your help here is very much appreciated! + #### Subscribe to Notifications for Your Language Check if there's a [GitHub Discussion](https://github.com/fastapi/fastapi/discussions/categories/translations) to coordinate translations for your language. You can subscribe to it, and when there's a new pull request to review, an automatic comment will be added to the discussion. diff --git a/docs/en/docs/management-tasks.md b/docs/en/docs/management-tasks.md index e4094c4a18..3388013a00 100644 --- a/docs/en/docs/management-tasks.md +++ b/docs/en/docs/management-tasks.md @@ -114,7 +114,14 @@ For these language translation PRs, confirm that: * The PR was automated (authored by @tiangolo), not made by another user. * It has the labels `lang-all` and `lang-{lang code}`. -* If the PR is approved by at least one native speaker, you can merge it. + +For PRs that update language-specific LLM prompts, confirm that: + +* The PR has the labels `lang-all` and `lang-{lang code}`. +* It is approved by at least one native speaker. +* In some cases you might need to translate several pages with new prompt to make sure it works as expected. + +If the PR meets the above conditions, you can merge it. 😎 ## Review PRs From 68ac0ab91e9b14c418013790fc0e420a827686b5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Mar 2026 13:59:57 +0000 Subject: [PATCH 26/69] =?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 bb3c0f117e..3111ff735d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Docs +* 📝 Update docs for contributors and team members regarding translation PRs. PR [#15200](https://github.com/fastapi/fastapi/pull/15200) by [@YuriiMotov](https://github.com/YuriiMotov). * 💄 Fix code blocks in reference docs overflowing table width. PR [#15094](https://github.com/fastapi/fastapi/pull/15094) by [@YuriiMotov](https://github.com/YuriiMotov). * 📝 Fix duplicated words in docstrings. PR [#15116](https://github.com/fastapi/fastapi/pull/15116) by [@AhsanSheraz](https://github.com/AhsanSheraz). * 📝 Add docs for `pyproject.toml` with `entrypoint`. PR [#15075](https://github.com/fastapi/fastapi/pull/15075) by [@tiangolo](https://github.com/tiangolo). From 122b6d490f844b6f716855d55a3e11237b7fb61f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 23 Mar 2026 15:08:07 +0100 Subject: [PATCH 27/69] =?UTF-8?q?=F0=9F=93=9D=20Add=20missing=20last=20rel?= =?UTF-8?q?ease=20notes=20dates=20(#15202)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3111ff735d..1ef2fc29c7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -73,7 +73,7 @@ hide: * ⬆ Bump actions/download-artifact from 7 to 8. PR [#15020](https://github.com/fastapi/fastapi/pull/15020) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump actions/upload-artifact from 6 to 7. PR [#15019](https://github.com/fastapi/fastapi/pull/15019) by [@dependabot[bot]](https://github.com/apps/dependabot). -## 0.135.1 +## 0.135.1 (2026-03-01) ### Fixes @@ -90,14 +90,14 @@ hide: * 👥 Update FastAPI People - Contributors and Translators. PR [#15029](https://github.com/fastapi/fastapi/pull/15029) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI GitHub topic repositories. PR [#15036](https://github.com/fastapi/fastapi/pull/15036) by [@tiangolo](https://github.com/tiangolo). -## 0.135.0 +## 0.135.0 (2026-03-01) ### Features * ✨ Add support for Server Sent Events. PR [#15030](https://github.com/fastapi/fastapi/pull/15030) by [@tiangolo](https://github.com/tiangolo). * New docs: [Server-Sent Events (SSE)](https://fastapi.tiangolo.com/tutorial/server-sent-events/). -## 0.134.0 +## 0.134.0 (2026-02-27) ### Features @@ -117,7 +117,7 @@ hide: * 🔨 Run tests with `pytest-xdist` and `pytest-cov`. PR [#14992](https://github.com/fastapi/fastapi/pull/14992) by [@YuriiMotov](https://github.com/YuriiMotov). -## 0.133.1 +## 0.133.1 (2026-02-25) ### Features From ab125daa4034435777853a2c5a6c47451414f9aa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Mar 2026 14:08:35 +0000 Subject: [PATCH 28/69] =?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 1ef2fc29c7..84d3765479 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Docs +* 📝 Add missing last release notes dates. PR [#15202](https://github.com/fastapi/fastapi/pull/15202) by [@tiangolo](https://github.com/tiangolo). * 📝 Update docs for contributors and team members regarding translation PRs. PR [#15200](https://github.com/fastapi/fastapi/pull/15200) by [@YuriiMotov](https://github.com/YuriiMotov). * 💄 Fix code blocks in reference docs overflowing table width. PR [#15094](https://github.com/fastapi/fastapi/pull/15094) by [@YuriiMotov](https://github.com/YuriiMotov). * 📝 Fix duplicated words in docstrings. PR [#15116](https://github.com/fastapi/fastapi/pull/15116) by [@AhsanSheraz](https://github.com/AhsanSheraz). From 25a3697cedc6e7dfb84e93c8ff965801486f00f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 23 Mar 2026 15:10:41 +0100 Subject: [PATCH 29/69] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.135.?= =?UTF-8?q?2?= 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 84d3765479..387973e56f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.135.2 (2026-03-01) + ### Upgrades * ⬆️ Increase lower bound to `pydantic >=2.9.0.` and fix the test suite. PR [#15139](https://github.com/fastapi/fastapi/pull/15139) by [@svlandeg](https://github.com/svlandeg). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 06dacbd9dc..5ab8b2c955 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.135.1" +__version__ = "0.135.2" from starlette import status as status From fa3588c38c7473aca7536b12d686102de4b0f407 Mon Sep 17 00:00:00 2001 From: Kadir Can Ozden <101993364+bysiber@users.noreply.github.com> Date: Tue, 24 Mar 2026 19:32:10 +0300 Subject: [PATCH 30/69] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fix=20typo=20for=20`?= =?UTF-8?q?client=5Fsecret`=20in=20OAuth2=20form=20docstrings=20(#14946)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 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 42674b476c..3fd9e41eb3 100644 --- a/fastapi/security/oauth2.py +++ b/fastapi/security/oauth2.py @@ -143,7 +143,7 @@ class OAuth2PasswordRequestForm: Form(json_schema_extra={"format": "password"}), Doc( """ - If there's a `client_password` (and a `client_id`), they can be sent + If there's a `client_secret` (and a `client_id`), they can be sent as part of the form fields. But the OAuth2 specification recommends sending the `client_id` and `client_secret` (if any) using HTTP Basic auth. @@ -309,7 +309,7 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm): Form(), Doc( """ - If there's a `client_password` (and a `client_id`), they can be sent + If there's a `client_secret` (and a `client_id`), they can be sent as part of the form fields. But the OAuth2 specification recommends sending the `client_id` and `client_secret` (if any) using HTTP Basic auth. From e2a0fd4ad851e45487f3f058a752107fe90bcad8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 24 Mar 2026 16:32:36 +0000 Subject: [PATCH 31/69] =?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 387973e56f..3a363c6593 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* ✏️ Fix typo for `client_secret` in OAuth2 form docstrings. PR [#14946](https://github.com/fastapi/fastapi/pull/14946) by [@bysiber](https://github.com/bysiber). + ## 0.135.2 (2026-03-01) ### Upgrades From 8238446b1beafb153b5fc0fef43341fe90690646 Mon Sep 17 00:00:00 2001 From: Sofie Van Landeghem Date: Tue, 24 Mar 2026 17:39:32 +0100 Subject: [PATCH 32/69] =?UTF-8?q?=F0=9F=91=B7=20Add=20ty=20check=20to=20`l?= =?UTF-8?q?int.sh`=20(#15136)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/lint.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/lint.sh b/scripts/lint.sh index 18cf52a848..a4d3422d3a 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -4,5 +4,6 @@ set -e set -x mypy fastapi +ty check fastapi ruff check fastapi tests docs_src scripts ruff format fastapi tests --check From 937d3075f9456dfcdfe2e1f6bc3b8b7b9a6c6cad Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 24 Mar 2026 16:39:58 +0000 Subject: [PATCH 33/69] =?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 3a363c6593..ebc1c79e2d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * ✏️ Fix typo for `client_secret` in OAuth2 form docstrings. PR [#14946](https://github.com/fastapi/fastapi/pull/14946) by [@bysiber](https://github.com/bysiber). +### Internal + +* 👷 Add ty check to `lint.sh`. PR [#15136](https://github.com/fastapi/fastapi/pull/15136) by [@svlandeg](https://github.com/svlandeg). + ## 0.135.2 (2026-03-01) ### Upgrades From 3b9d8481c5359545051a6d743a1f9a429ae4ce5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 22:52:50 +0100 Subject: [PATCH 34/69] =?UTF-8?q?=E2=AC=86=20Bump=20requests=20from=202.32?= =?UTF-8?q?.5=20to=202.33.0=20(#15228)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index 90e9b4e462..d43cde229c 100644 --- a/uv.lock +++ b/uv.lock @@ -1984,6 +1984,7 @@ wheels = [ name = "griffelib" version = "2.0.0" source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ad/06/eccbd311c9e2b3ca45dbc063b93134c57a1ccc7607c5e545264ad092c4a9/griffelib-2.0.0.tar.gz", hash = "sha256:e504d637a089f5cab9b5daf18f7645970509bf4f53eda8d79ed71cce8bd97934", size = 166312, upload-time = "2026-03-23T21:06:55.954Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl", hash = "sha256:01284878c966508b6d6f1dbff9b6fa607bc062d8261c5c7253cb285b06422a7f", size = 142004, upload-time = "2026-02-09T19:09:40.561Z" }, ] @@ -4859,7 +4860,7 @@ wheels = [ [[package]] name = "requests" -version = "2.32.5" +version = "2.33.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -4867,9 +4868,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +sdist = { url = "https://files.pythonhosted.org/packages/34/64/8860370b167a9721e8956ae116825caff829224fbca0ca6e7bf8ddef8430/requests-2.33.0.tar.gz", hash = "sha256:c7ebc5e8b0f21837386ad0e1c8fe8b829fa5f544d8df3b2253bff14ef29d7652", size = 134232, upload-time = "2026-03-25T15:10:41.586Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, + { url = "https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl", hash = "sha256:3324635456fa185245e24865e810cecec7b4caf933d7eb133dcde67d48cee69b", size = 65017, upload-time = "2026-03-25T15:10:40.382Z" }, ] [[package]] From d128a7089a645466b789e32097de125a3b0f8979 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 26 Mar 2026 21:53:12 +0000 Subject: [PATCH 35/69] =?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 ebc1c79e2d..c2f6a0e9ee 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* ⬆ Bump requests from 2.32.5 to 2.33.0. PR [#15228](https://github.com/fastapi/fastapi/pull/15228) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👷 Add ty check to `lint.sh`. PR [#15136](https://github.com/fastapi/fastapi/pull/15136) by [@svlandeg](https://github.com/svlandeg). ## 0.135.2 (2026-03-01) From 81194139aa8718728dfb63ff3083de5abc37fb6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Apr 2026 09:31:54 +0200 Subject: [PATCH 36/69] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20People?= =?UTF-8?q?=20-=20Contributors=20and=20Translators=20(#15270)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/data/contributors.yml | 18 ++++++++++++++---- docs/en/data/translation_reviewers.yml | 12 ++++++------ docs/en/data/translators.yml | 12 ++++++------ 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index 15721587a1..e003b3a42a 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,16 +1,16 @@ tiangolo: login: tiangolo - count: 922 + count: 935 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 142 + count: 157 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 url: https://github.com/apps/dependabot YuriiMotov: login: YuriiMotov - count: 57 + count: 66 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov alejsdev: @@ -35,7 +35,7 @@ Kludex: url: https://github.com/Kludex svlandeg: login: svlandeg - count: 18 + count: 21 avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 url: https://github.com/svlandeg dmontagu: @@ -508,6 +508,11 @@ joakimnordling: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/6637576?u=df5d99db9b899b399effd429f4358baaa6f7199c&v=4 url: https://github.com/joakimnordling +AhsanSheraz: + login: AhsanSheraz + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/51913596?u=b5aa3c3a004cc0112e56c54f6901941836d8c26b&v=4 + url: https://github.com/AhsanSheraz yogabonito: login: yogabonito count: 2 @@ -573,6 +578,11 @@ Taoup: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/22348542?v=4 url: https://github.com/Taoup +savannahostrowski: + login: savannahostrowski + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/8949415?u=e4bb61b9ebaa406274d2f2629cd33179a432a2a7&v=4 + url: https://github.com/savannahostrowski jonathan-fulton: login: jonathan-fulton count: 2 diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index 73f6dc6f0d..480bf72f38 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -65,7 +65,7 @@ nilslindemann: url: https://github.com/nilslindemann YuriiMotov: login: YuriiMotov - count: 65 + count: 66 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov cassiobotaro: @@ -671,7 +671,7 @@ riroan: MinLee0210: login: MinLee0210 count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=8ca05a7efbc76048183da00da87d148b755a3ba8&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=e7c4d8d7eeb7bceed1680ef0e5dafec0695f57e0&v=4 url: https://github.com/MinLee0210 yodai-yodai: login: yodai-yodai @@ -1081,7 +1081,7 @@ bas-baskara: odiseo0: login: odiseo0 count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=241a71f6b7068738b81af3e57f45ffd723538401&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=75e754b9bd12ce6dfe90ad68e82e6f5255c7ac09&v=4 url: https://github.com/odiseo0 eryknn: login: eryknn @@ -1681,7 +1681,7 @@ theRealNonso: AhsanSheraz: login: AhsanSheraz count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/51913596?u=08e31cacb3048be30722c94010ddd028f3fdbec4&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/51913596?u=b5aa3c3a004cc0112e56c54f6901941836d8c26b&v=4 url: https://github.com/AhsanSheraz HealerNguyen: login: HealerNguyen @@ -1706,7 +1706,7 @@ Ramin-RX7: DevSpace88: login: DevSpace88 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/102557040?u=6b356e3e1b9b6bc6a208b363988d4089ef94193f&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/102557040?u=103e454f0d4d2d357bd66e9931e57f0bf267526a&v=4 url: https://github.com/DevSpace88 Yum-git: login: Yum-git @@ -1856,7 +1856,7 @@ Azazul123: ykertytsky: login: ykertytsky count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/83857001?u=1172902656ee604cf37f5e36abe938cd34a97a32&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/83857001?u=1f303eb73189f78cff376c13bd46db65f90ee314&v=4 url: https://github.com/ykertytsky NavesSapnis: login: NavesSapnis diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index 38a3306dc4..395025f443 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -3,16 +3,16 @@ nilslindemann: count: 130 avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 url: https://github.com/nilslindemann +tiangolo: + login: tiangolo + count: 67 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo jaystone776: login: jaystone776 count: 46 avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4 url: https://github.com/jaystone776 -tiangolo: - login: tiangolo - count: 46 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo ceb10n: login: ceb10n count: 30 @@ -456,7 +456,7 @@ TabarakoAkula: AhsanSheraz: login: AhsanSheraz count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/51913596?u=08e31cacb3048be30722c94010ddd028f3fdbec4&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/51913596?u=b5aa3c3a004cc0112e56c54f6901941836d8c26b&v=4 url: https://github.com/AhsanSheraz ArtemKhymenko: login: ArtemKhymenko From a15609f56d1dfc940f6b9eee0a98bc8fb1154243 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Apr 2026 07:32:21 +0000 Subject: [PATCH 37/69] =?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 c2f6a0e9ee..ea26953fa3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Contributors and Translators. PR [#15270](https://github.com/fastapi/fastapi/pull/15270) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump requests from 2.32.5 to 2.33.0. PR [#15228](https://github.com/fastapi/fastapi/pull/15228) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👷 Add ty check to `lint.sh`. PR [#15136](https://github.com/fastapi/fastapi/pull/15136) by [@svlandeg](https://github.com/svlandeg). From cb4fe1b453068c30b13de2d97b13cae5cca97bd1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 09:33:06 +0200 Subject: [PATCH 38/69] =?UTF-8?q?=E2=AC=86=20Bump=20fastmcp=20from=202.14.?= =?UTF-8?q?5=20to=203.2.0=20(#15267)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 302 ++++++++++++-------------------------------------------- 1 file changed, 65 insertions(+), 237 deletions(-) diff --git a/uv.lock b/uv.lock index d43cde229c..8fd075b526 100644 --- a/uv.lock +++ b/uv.lock @@ -30,6 +30,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8f/78/eb55fabaab41abc53f52c0918a9a8c0f747807e5306273f51120fd695957/ag_ui_protocol-0.1.10-py3-none-any.whl", hash = "sha256:c81e6981f30aabdf97a7ee312bfd4df0cd38e718d9fc10019c7d438128b93ab5", size = 7889, upload-time = "2025-11-06T15:17:15.325Z" }, ] +[[package]] +name = "aiofile" +version = "3.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "caio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/67/e2/d7cb819de8df6b5c1968a2756c3cb4122d4fa2b8fc768b53b7c9e5edb646/aiofile-3.9.0.tar.gz", hash = "sha256:e5ad718bb148b265b6df1b3752c4d1d83024b93da9bd599df74b9d9ffcf7919b", size = 17943, upload-time = "2024-10-08T10:39:35.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/50/25/da1f0b4dd970e52bf5a36c204c107e11a0c6d3ed195eba0bfbc664c312b2/aiofile-3.9.0-py3-none-any.whl", hash = "sha256:ce2f6c1571538cbdfa0143b04e16b208ecb0e9cb4148e528af8a640ed51cc8aa", size = 19539, upload-time = "2024-10-08T10:39:32.955Z" }, +] + [[package]] name = "aiohappyeyeballs" version = "2.6.1" @@ -455,6 +467,35 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/28/df/2dd32cce20cbcf6f2ec456b58d44368161ad28320729f64e5e1d5d7bd0ae/cachetools-7.0.0-py3-none-any.whl", hash = "sha256:d52fef60e6e964a1969cfb61ccf6242a801b432790fe520d78720d757c81cbd2", size = 13487, upload-time = "2026-02-01T18:59:45.981Z" }, ] +[[package]] +name = "caio" +version = "0.9.25" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/88/b8527e1b00c1811db339a1df8bd1ae49d146fcea9d6a5c40e3a80aaeb38d/caio-0.9.25.tar.gz", hash = "sha256:16498e7f81d1d0f5a4c0ad3f2540e65fe25691376e0a5bd367f558067113ed10", size = 26781, upload-time = "2025-12-26T15:21:36.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/80/ea4ead0c5d52a9828692e7df20f0eafe8d26e671ce4883a0a146bb91049e/caio-0.9.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ca6c8ecda611478b6016cb94d23fd3eb7124852b985bdec7ecaad9f3116b9619", size = 36836, upload-time = "2025-12-26T15:22:04.662Z" }, + { url = "https://files.pythonhosted.org/packages/17/b9/36715c97c873649d1029001578f901b50250916295e3dddf20c865438865/caio-0.9.25-cp310-cp310-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:db9b5681e4af8176159f0d6598e73b2279bb661e718c7ac23342c550bd78c241", size = 79695, upload-time = "2025-12-26T15:22:18.818Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ab/07080ecb1adb55a02cbd8ec0126aa8e43af343ffabb6a71125b42670e9a1/caio-0.9.25-cp310-cp310-manylinux_2_34_aarch64.whl", hash = "sha256:bf61d7d0c4fd10ffdd98ca47f7e8db4d7408e74649ffaf4bef40b029ada3c21b", size = 79457, upload-time = "2026-03-04T22:08:16.024Z" }, + { url = "https://files.pythonhosted.org/packages/88/95/dd55757bb671eb4c376e006c04e83beb413486821f517792ea603ef216e9/caio-0.9.25-cp310-cp310-manylinux_2_34_x86_64.whl", hash = "sha256:ab52e5b643f8bbd64a0605d9412796cd3464cb8ca88593b13e95a0f0b10508ae", size = 77705, upload-time = "2026-03-04T22:08:17.202Z" }, + { url = "https://files.pythonhosted.org/packages/ec/90/543f556fcfcfa270713eef906b6352ab048e1e557afec12925c991dc93c2/caio-0.9.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d6956d9e4a27021c8bd6c9677f3a59eb1d820cc32d0343cea7961a03b1371965", size = 36839, upload-time = "2025-12-26T15:21:40.267Z" }, + { url = "https://files.pythonhosted.org/packages/51/3b/36f3e8ec38dafe8de4831decd2e44c69303d2a3892d16ceda42afed44e1b/caio-0.9.25-cp311-cp311-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bf84bfa039f25ad91f4f52944452a5f6f405e8afab4d445450978cd6241d1478", size = 80255, upload-time = "2025-12-26T15:22:20.271Z" }, + { url = "https://files.pythonhosted.org/packages/df/ce/65e64867d928e6aff1b4f0e12dba0ef6d5bf412c240dc1df9d421ac10573/caio-0.9.25-cp311-cp311-manylinux_2_34_aarch64.whl", hash = "sha256:ae3d62587332bce600f861a8de6256b1014d6485cfd25d68c15caf1611dd1f7c", size = 80052, upload-time = "2026-03-04T22:08:20.402Z" }, + { url = "https://files.pythonhosted.org/packages/46/90/e278863c47e14ec58309aa2e38a45882fbe67b4cc29ec9bc8f65852d3e45/caio-0.9.25-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:fc220b8533dcf0f238a6b1a4a937f92024c71e7b10b5a2dfc1c73604a25709bc", size = 78273, upload-time = "2026-03-04T22:08:21.368Z" }, + { url = "https://files.pythonhosted.org/packages/d3/25/79c98ebe12df31548ba4eaf44db11b7cad6b3e7b4203718335620939083c/caio-0.9.25-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fb7ff95af4c31ad3f03179149aab61097a71fd85e05f89b4786de0359dffd044", size = 36983, upload-time = "2025-12-26T15:21:36.075Z" }, + { url = "https://files.pythonhosted.org/packages/a3/2b/21288691f16d479945968a0a4f2856818c1c5be56881d51d4dac9b255d26/caio-0.9.25-cp312-cp312-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:97084e4e30dfa598449d874c4d8e0c8d5ea17d2f752ef5e48e150ff9d240cd64", size = 82012, upload-time = "2025-12-26T15:22:20.983Z" }, + { url = "https://files.pythonhosted.org/packages/03/c4/8a1b580875303500a9c12b9e0af58cb82e47f5bcf888c2457742a138273c/caio-0.9.25-cp312-cp312-manylinux_2_34_aarch64.whl", hash = "sha256:4fa69eba47e0f041b9d4f336e2ad40740681c43e686b18b191b6c5f4c5544bfb", size = 81502, upload-time = "2026-03-04T22:08:22.381Z" }, + { url = "https://files.pythonhosted.org/packages/d1/1c/0fe770b8ffc8362c48134d1592d653a81a3d8748d764bec33864db36319d/caio-0.9.25-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:6bebf6f079f1341d19f7386db9b8b1f07e8cc15ae13bfdaff573371ba0575d69", size = 80200, upload-time = "2026-03-04T22:08:23.382Z" }, + { url = "https://files.pythonhosted.org/packages/31/57/5e6ff127e6f62c9f15d989560435c642144aa4210882f9494204bc892305/caio-0.9.25-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d6c2a3411af97762a2b03840c3cec2f7f728921ff8adda53d7ea2315a8563451", size = 36979, upload-time = "2025-12-26T15:21:35.484Z" }, + { url = "https://files.pythonhosted.org/packages/a3/9f/f21af50e72117eb528c422d4276cbac11fb941b1b812b182e0a9c70d19c5/caio-0.9.25-cp313-cp313-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0998210a4d5cd5cb565b32ccfe4e53d67303f868a76f212e002a8554692870e6", size = 81900, upload-time = "2025-12-26T15:22:21.919Z" }, + { url = "https://files.pythonhosted.org/packages/9c/12/c39ae2a4037cb10ad5eb3578eb4d5f8c1a2575c62bba675f3406b7ef0824/caio-0.9.25-cp313-cp313-manylinux_2_34_aarch64.whl", hash = "sha256:1a177d4777141b96f175fe2c37a3d96dec7911ed9ad5f02bac38aaa1c936611f", size = 81523, upload-time = "2026-03-04T22:08:25.187Z" }, + { url = "https://files.pythonhosted.org/packages/22/59/f8f2e950eb4f1a5a3883e198dca514b9d475415cb6cd7b78b9213a0dd45a/caio-0.9.25-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:9ed3cfb28c0e99fec5e208c934e5c157d0866aa9c32aa4dc5e9b6034af6286b7", size = 80243, upload-time = "2026-03-04T22:08:26.449Z" }, + { url = "https://files.pythonhosted.org/packages/69/ca/a08fdc7efdcc24e6a6131a93c85be1f204d41c58f474c42b0670af8c016b/caio-0.9.25-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fab6078b9348e883c80a5e14b382e6ad6aabbc4429ca034e76e730cf464269db", size = 36978, upload-time = "2025-12-26T15:21:41.055Z" }, + { url = "https://files.pythonhosted.org/packages/5e/6c/d4d24f65e690213c097174d26eda6831f45f4734d9d036d81790a27e7b78/caio-0.9.25-cp314-cp314-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:44a6b58e52d488c75cfaa5ecaa404b2b41cc965e6c417e03251e868ecd5b6d77", size = 81832, upload-time = "2025-12-26T15:22:22.757Z" }, + { url = "https://files.pythonhosted.org/packages/87/a4/e534cf7d2d0e8d880e25dd61e8d921ffcfe15bd696734589826f5a2df727/caio-0.9.25-cp314-cp314-manylinux_2_34_aarch64.whl", hash = "sha256:628a630eb7fb22381dd8e3c8ab7f59e854b9c806639811fc3f4310c6bd711d79", size = 81565, upload-time = "2026-03-04T22:08:27.483Z" }, + { url = "https://files.pythonhosted.org/packages/3f/ed/bf81aeac1d290017e5e5ac3e880fd56ee15e50a6d0353986799d1bc5cfd5/caio-0.9.25-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:0ba16aa605ccb174665357fc729cf500679c2d94d5f1458a6f0d5ca48f2060a7", size = 80071, upload-time = "2026-03-04T22:08:28.751Z" }, + { url = "https://files.pythonhosted.org/packages/86/93/1f76c8d1bafe3b0614e06b2195784a3765bbf7b0a067661af9e2dd47fc33/caio-0.9.25-py3-none-any.whl", hash = "sha256:06c0bb02d6b929119b1cfbe1ca403c768b2013a369e2db46bfa2a5761cf82e40", size = 19087, upload-time = "2025-12-26T15:22:00.221Z" }, +] + [[package]] name = "cairocffi" version = "1.7.1" @@ -675,15 +716,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, ] -[[package]] -name = "cloudpickle" -version = "3.1.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/27/fb/576f067976d320f5f0114a8d9fa1215425441bb35627b1993e5afd8111e5/cloudpickle-3.1.2.tar.gz", hash = "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414", size = 22330, upload-time = "2025-11-03T09:25:26.604Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl", hash = "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a", size = 22228, upload-time = "2025-11-03T09:25:25.534Z" }, -] - [[package]] name = "cohere" version = "5.20.7" @@ -816,19 +848,6 @@ toml = [ { name = "tomli", marker = "python_full_version <= '3.11'" }, ] -[[package]] -name = "croniter" -version = "6.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "python-dateutil" }, - { name = "pytz" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ad/2f/44d1ae153a0e27be56be43465e5cb39b9650c781e001e7864389deb25090/croniter-6.0.0.tar.gz", hash = "sha256:37c504b313956114a983ece2c2b07790b1f1094fe9d81cc94739214748255577", size = 64481, upload-time = "2024-12-17T17:17:47.32Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/07/4b/290b4c3efd6417a8b0c284896de19b1d5855e6dbdb97d2a35e68fa42de85/croniter-6.0.0-py2.py3-none-any.whl", hash = "sha256:2f878c3856f17896979b2a4379ba1f09c83e374931ea15cc835c5dd2eee9b368", size = 25468, upload-time = "2024-12-17T17:17:45.359Z" }, -] - [[package]] name = "cross-web" version = "0.4.1" @@ -958,15 +977,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/bb/8d/dbff05239043271dbeace563a7686212a3dd517864a35623fe4d4a64ca19/dirty_equals-0.11-py3-none-any.whl", hash = "sha256:b1d7093273fc2f9be12f443a8ead954ef6daaf6746fd42ef3a5616433ee85286", size = 28051, upload-time = "2025-11-17T01:51:22.849Z" }, ] -[[package]] -name = "diskcache" -version = "5.6.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3f/21/1c1ffc1a039ddcc459db43cc108658f32c57d271d7289a2794e401d0fdb6/diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc", size = 67916, upload-time = "2023-08-31T06:12:00.316Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/27/4570e78fc0bf5ea0ca45eb1de3818a23787af9b390c0b0a0033a1b8236f9/diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19", size = 45550, upload-time = "2023-08-31T06:11:58.822Z" }, -] - [[package]] name = "distro" version = "1.9.0" @@ -1055,25 +1065,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, ] -[[package]] -name = "fakeredis" -version = "2.33.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "redis" }, - { name = "sortedcontainers" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/5f/f9/57464119936414d60697fcbd32f38909bb5688b616ae13de6e98384433e0/fakeredis-2.33.0.tar.gz", hash = "sha256:d7bc9a69d21df108a6451bbffee23b3eba432c21a654afc7ff2d295428ec5770", size = 175187, upload-time = "2025-12-16T19:45:52.269Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6e/78/a850fed8aeef96d4a99043c90b818b2ed5419cd5b24a4049fd7cfb9f1471/fakeredis-2.33.0-py3-none-any.whl", hash = "sha256:de535f3f9ccde1c56672ab2fdd6a8efbc4f2619fc2f1acc87b8737177d71c965", size = 119605, upload-time = "2025-12-16T19:45:51.08Z" }, -] - -[package.optional-dependencies] -lua = [ - { name = "lupa" }, -] - [[package]] name = "fastapi" source = { editable = "." } @@ -1602,7 +1593,7 @@ wheels = [ [[package]] name = "fastmcp" -version = "2.14.5" +version = "3.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "authlib" }, @@ -1613,20 +1604,23 @@ dependencies = [ { name = "jsonschema-path" }, { name = "mcp" }, { name = "openapi-pydantic" }, + { name = "opentelemetry-api" }, { name = "packaging" }, { name = "platformdirs" }, - { name = "py-key-value-aio", extra = ["disk", "keyring", "memory"] }, + { name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] }, { name = "pydantic", extra = ["email"] }, - { name = "pydocket" }, { name = "pyperclip" }, { name = "python-dotenv" }, + { name = "pyyaml" }, { name = "rich" }, + { name = "uncalled-for" }, { name = "uvicorn" }, + { name = "watchfiles" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3b/32/982678d44f13849530a74ab101ed80e060c2ee6cf87471f062dcf61705fd/fastmcp-2.14.5.tar.gz", hash = "sha256:38944dc582c541d55357082bda2241cedb42cd3a78faea8a9d6a2662c62a42d7", size = 8296329, upload-time = "2026-02-03T15:35:21.005Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/32/4f1b2cfd7b50db89114949f90158b1dcc2c92a1917b9f57c0ff24e47a2f4/fastmcp-3.2.0.tar.gz", hash = "sha256:d4830b8ffc3592d3d9c76dc0f398904cf41f04910e41a0de38cc1004e0903bef", size = 26318581, upload-time = "2026-03-30T20:25:37.692Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/c1/1a35ec68ff76ea8443aa115b18bcdee748a4ada2124537ee90522899ff9f/fastmcp-2.14.5-py3-none-any.whl", hash = "sha256:d81e8ec813f5089d3624bec93944beaefa86c0c3a4ef1111cbef676a761ebccf", size = 417784, upload-time = "2026-02-03T15:35:18.489Z" }, + { url = "https://files.pythonhosted.org/packages/4f/67/684fa2d2de1e7504549d4ca457b4f854ccec3cd3be03bd86b33b599fbf58/fastmcp-3.2.0-py3-none-any.whl", hash = "sha256:e71aba3df16f86f546a4a9e513261d3233bcc92bef0dfa647bac3fa33623f681", size = 705550, upload-time = "2026-03-30T20:25:35.499Z" }, ] [[package]] @@ -2623,80 +2617,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1e/93/4e8395f3e4b1951b1de8d06cb7d7ef1105efd294ea3443bf39b3594390af/logfire_api-4.22.0-py3-none-any.whl", hash = "sha256:9fd2a2dac9cc3adf71ad4dac7bc9d26af326a5aa87445be90026048d22b92a8e", size = 98543, upload-time = "2026-02-04T12:17:56.365Z" }, ] -[[package]] -name = "lupa" -version = "2.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b8/1c/191c3e6ec6502e3dbe25a53e27f69a5daeac3e56de1f73c0138224171ead/lupa-2.6.tar.gz", hash = "sha256:9a770a6e89576be3447668d7ced312cd6fd41d3c13c2462c9dc2c2ab570e45d9", size = 7240282, upload-time = "2025-10-24T07:20:29.738Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a1/15/713cab5d0dfa4858f83b99b3e0329072df33dc14fc3ebbaa017e0f9755c4/lupa-2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6b3dabda836317e63c5ad052826e156610f356a04b3003dfa0dbe66b5d54d671", size = 954828, upload-time = "2025-10-24T07:17:15.726Z" }, - { url = "https://files.pythonhosted.org/packages/2e/71/704740cbc6e587dd6cc8dabf2f04820ac6a671784e57cc3c29db795476db/lupa-2.6-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:8726d1c123bbe9fbb974ce29825e94121824e66003038ff4532c14cc2ed0c51c", size = 1919259, upload-time = "2025-10-24T07:17:18.586Z" }, - { url = "https://files.pythonhosted.org/packages/eb/18/f248341c423c5d48837e35584c6c3eb4acab7e722b6057d7b3e28e42dae8/lupa-2.6-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:f4e159e7d814171199b246f9235ca8961f6461ea8c1165ab428afa13c9289a94", size = 984998, upload-time = "2025-10-24T07:17:20.428Z" }, - { url = "https://files.pythonhosted.org/packages/44/1e/8a4bd471e018aad76bcb9455d298c2c96d82eced20f2ae8fcec8cd800948/lupa-2.6-cp310-cp310-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:202160e80dbfddfb79316692a563d843b767e0f6787bbd1c455f9d54052efa6c", size = 1174871, upload-time = "2025-10-24T07:17:22.755Z" }, - { url = "https://files.pythonhosted.org/packages/2a/5c/3a3f23fd6a91b0986eea1ceaf82ad3f9b958fe3515a9981fb9c4eb046c8b/lupa-2.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5deede7c5b36ab64f869dae4831720428b67955b0bb186c8349cf6ea121c852b", size = 1057471, upload-time = "2025-10-24T07:17:24.908Z" }, - { url = "https://files.pythonhosted.org/packages/45/ac/01be1fed778fb0c8f46ee8cbe344e4d782f6806fac12717f08af87aa4355/lupa-2.6-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:86f04901f920bbf7c0cac56807dc9597e42347123e6f1f3ca920f15f54188ce5", size = 2100592, upload-time = "2025-10-24T07:17:27.089Z" }, - { url = "https://files.pythonhosted.org/packages/3f/6c/1a05bb873e30830f8574e10cd0b4cdbc72e9dbad2a09e25810b5e3b1f75d/lupa-2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6deef8f851d6afb965c84849aa5b8c38856942df54597a811ce0369ced678610", size = 1081396, upload-time = "2025-10-24T07:17:29.064Z" }, - { url = "https://files.pythonhosted.org/packages/a2/c2/a19dd80d6dc98b39bbf8135b8198e38aa7ca3360b720eac68d1d7e9286b5/lupa-2.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:21f2b5549681c2a13b1170a26159d30875d367d28f0247b81ca347222c755038", size = 1192007, upload-time = "2025-10-24T07:17:31.362Z" }, - { url = "https://files.pythonhosted.org/packages/4f/43/e1b297225c827f55752e46fdbfb021c8982081b0f24490e42776ea69ae3b/lupa-2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:66eea57630eab5e6f49fdc5d7811c0a2a41f2011be4ea56a087ea76112011eb7", size = 2196661, upload-time = "2025-10-24T07:17:33.484Z" }, - { url = "https://files.pythonhosted.org/packages/2e/8f/2272d429a7fa9dc8dbd6e9c5c9073a03af6007eb22a4c78829fec6a34b80/lupa-2.6-cp310-cp310-win32.whl", hash = "sha256:60a403de8cab262a4fe813085dd77010effa6e2eb1886db2181df803140533b1", size = 1412738, upload-time = "2025-10-24T07:17:35.11Z" }, - { url = "https://files.pythonhosted.org/packages/35/2a/1708911271dd49ad87b4b373b5a4b0e0a0516d3d2af7b76355946c7ee171/lupa-2.6-cp310-cp310-win_amd64.whl", hash = "sha256:e4656a39d93dfa947cf3db56dc16c7916cb0cc8024acd3a952071263f675df64", size = 1656898, upload-time = "2025-10-24T07:17:36.949Z" }, - { url = "https://files.pythonhosted.org/packages/ca/29/1f66907c1ebf1881735afa695e646762c674f00738ebf66d795d59fc0665/lupa-2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6d988c0f9331b9f2a5a55186701a25444ab10a1432a1021ee58011499ecbbdd5", size = 962875, upload-time = "2025-10-24T07:17:39.107Z" }, - { url = "https://files.pythonhosted.org/packages/e6/67/4a748604be360eb9c1c215f6a0da921cd1a2b44b2c5951aae6fb83019d3a/lupa-2.6-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:ebe1bbf48259382c72a6fe363dea61a0fd6fe19eab95e2ae881e20f3654587bf", size = 1935390, upload-time = "2025-10-24T07:17:41.427Z" }, - { url = "https://files.pythonhosted.org/packages/ac/0c/8ef9ee933a350428b7bdb8335a37ef170ab0bb008bbf9ca8f4f4310116b6/lupa-2.6-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:a8fcee258487cf77cdd41560046843bb38c2e18989cd19671dd1e2596f798306", size = 992193, upload-time = "2025-10-24T07:17:43.231Z" }, - { url = "https://files.pythonhosted.org/packages/65/46/e6c7facebdb438db8a65ed247e56908818389c1a5abbf6a36aab14f1057d/lupa-2.6-cp311-cp311-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:561a8e3be800827884e767a694727ed8482d066e0d6edfcbf423b05e63b05535", size = 1165844, upload-time = "2025-10-24T07:17:45.437Z" }, - { url = "https://files.pythonhosted.org/packages/1c/26/9f1154c6c95f175ccbf96aa96c8f569c87f64f463b32473e839137601a8b/lupa-2.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af880a62d47991cae78b8e9905c008cbfdc4a3a9723a66310c2634fc7644578c", size = 1048069, upload-time = "2025-10-24T07:17:47.181Z" }, - { url = "https://files.pythonhosted.org/packages/68/67/2cc52ab73d6af81612b2ea24c870d3fa398443af8e2875e5befe142398b1/lupa-2.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:80b22923aa4023c86c0097b235615f89d469a0c4eee0489699c494d3367c4c85", size = 2079079, upload-time = "2025-10-24T07:17:49.755Z" }, - { url = "https://files.pythonhosted.org/packages/2e/dc/f843f09bbf325f6e5ee61730cf6c3409fc78c010d968c7c78acba3019ca7/lupa-2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:153d2cc6b643f7efb9cfc0c6bb55ec784d5bac1a3660cfc5b958a7b8f38f4a75", size = 1071428, upload-time = "2025-10-24T07:17:51.991Z" }, - { url = "https://files.pythonhosted.org/packages/2e/60/37533a8d85bf004697449acb97ecdacea851acad28f2ad3803662487dd2a/lupa-2.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3fa8777e16f3ded50b72967dc17e23f5a08e4f1e2c9456aff2ebdb57f5b2869f", size = 1181756, upload-time = "2025-10-24T07:17:53.752Z" }, - { url = "https://files.pythonhosted.org/packages/e4/f2/cf29b20dbb4927b6a3d27c339ac5d73e74306ecc28c8e2c900b2794142ba/lupa-2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8dbdcbe818c02a2f56f5ab5ce2de374dab03e84b25266cfbaef237829bc09b3f", size = 2175687, upload-time = "2025-10-24T07:17:56.228Z" }, - { url = "https://files.pythonhosted.org/packages/94/7c/050e02f80c7131b63db1474bff511e63c545b5a8636a24cbef3fc4da20b6/lupa-2.6-cp311-cp311-win32.whl", hash = "sha256:defaf188fde8f7a1e5ce3a5e6d945e533b8b8d547c11e43b96c9b7fe527f56dc", size = 1412592, upload-time = "2025-10-24T07:17:59.062Z" }, - { url = "https://files.pythonhosted.org/packages/6f/9a/6f2af98aa5d771cea661f66c8eb8f53772ec1ab1dfbce24126cfcd189436/lupa-2.6-cp311-cp311-win_amd64.whl", hash = "sha256:9505ae600b5c14f3e17e70f87f88d333717f60411faca1ddc6f3e61dce85fa9e", size = 1669194, upload-time = "2025-10-24T07:18:01.647Z" }, - { url = "https://files.pythonhosted.org/packages/94/86/ce243390535c39d53ea17ccf0240815e6e457e413e40428a658ea4ee4b8d/lupa-2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:47ce718817ef1cc0c40d87c3d5ae56a800d61af00fbc0fad1ca9be12df2f3b56", size = 951707, upload-time = "2025-10-24T07:18:03.884Z" }, - { url = "https://files.pythonhosted.org/packages/86/85/cedea5e6cbeb54396fdcc55f6b741696f3f036d23cfaf986d50d680446da/lupa-2.6-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:7aba985b15b101495aa4b07112cdc08baa0c545390d560ad5cfde2e9e34f4d58", size = 1916703, upload-time = "2025-10-24T07:18:05.6Z" }, - { url = "https://files.pythonhosted.org/packages/24/be/3d6b5f9a8588c01a4d88129284c726017b2089f3a3fd3ba8bd977292fea0/lupa-2.6-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:b766f62f95b2739f2248977d29b0722e589dcf4f0ccfa827ccbd29f0148bd2e5", size = 985152, upload-time = "2025-10-24T07:18:08.561Z" }, - { url = "https://files.pythonhosted.org/packages/eb/23/9f9a05beee5d5dce9deca4cb07c91c40a90541fc0a8e09db4ee670da550f/lupa-2.6-cp312-cp312-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:00a934c23331f94cb51760097ebfab14b005d55a6b30a2b480e3c53dd2fa290d", size = 1159599, upload-time = "2025-10-24T07:18:10.346Z" }, - { url = "https://files.pythonhosted.org/packages/40/4e/e7c0583083db9d7f1fd023800a9767d8e4391e8330d56c2373d890ac971b/lupa-2.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21de9f38bd475303e34a042b7081aabdf50bd9bafd36ce4faea2f90fd9f15c31", size = 1038686, upload-time = "2025-10-24T07:18:12.112Z" }, - { url = "https://files.pythonhosted.org/packages/1c/9f/5a4f7d959d4feba5e203ff0c31889e74d1ca3153122be4a46dca7d92bf7c/lupa-2.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf3bda96d3fc41237e964a69c23647d50d4e28421111360274d4799832c560e9", size = 2071956, upload-time = "2025-10-24T07:18:14.572Z" }, - { url = "https://files.pythonhosted.org/packages/92/34/2f4f13ca65d01169b1720176aedc4af17bc19ee834598c7292db232cb6dc/lupa-2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a76ead245da54801a81053794aa3975f213221f6542d14ec4b859ee2e7e0323", size = 1057199, upload-time = "2025-10-24T07:18:16.379Z" }, - { url = "https://files.pythonhosted.org/packages/35/2a/5f7d2eebec6993b0dcd428e0184ad71afb06a45ba13e717f6501bfed1da3/lupa-2.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8dd0861741caa20886ddbda0a121d8e52fb9b5bb153d82fa9bba796962bf30e8", size = 1173693, upload-time = "2025-10-24T07:18:18.153Z" }, - { url = "https://files.pythonhosted.org/packages/e4/29/089b4d2f8e34417349af3904bb40bec40b65c8731f45e3fd8d497ca573e5/lupa-2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:239e63948b0b23023f81d9a19a395e768ed3da6a299f84e7963b8f813f6e3f9c", size = 2164394, upload-time = "2025-10-24T07:18:20.403Z" }, - { url = "https://files.pythonhosted.org/packages/f3/1b/79c17b23c921f81468a111cad843b076a17ef4b684c4a8dff32a7969c3f0/lupa-2.6-cp312-cp312-win32.whl", hash = "sha256:325894e1099499e7a6f9c351147661a2011887603c71086d36fe0f964d52d1ce", size = 1420647, upload-time = "2025-10-24T07:18:23.368Z" }, - { url = "https://files.pythonhosted.org/packages/b8/15/5121e68aad3584e26e1425a5c9a79cd898f8a152292059e128c206ee817c/lupa-2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c735a1ce8ee60edb0fe71d665f1e6b7c55c6021f1d340eb8c865952c602cd36f", size = 1688529, upload-time = "2025-10-24T07:18:25.523Z" }, - { url = "https://files.pythonhosted.org/packages/28/1d/21176b682ca5469001199d8b95fa1737e29957a3d185186e7a8b55345f2e/lupa-2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:663a6e58a0f60e7d212017d6678639ac8df0119bc13c2145029dcba084391310", size = 947232, upload-time = "2025-10-24T07:18:27.878Z" }, - { url = "https://files.pythonhosted.org/packages/ce/4c/d327befb684660ca13cf79cd1f1d604331808f9f1b6fb6bf57832f8edf80/lupa-2.6-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:d1f5afda5c20b1f3217a80e9bc1b77037f8a6eb11612fd3ada19065303c8f380", size = 1908625, upload-time = "2025-10-24T07:18:29.944Z" }, - { url = "https://files.pythonhosted.org/packages/66/8e/ad22b0a19454dfd08662237a84c792d6d420d36b061f239e084f29d1a4f3/lupa-2.6-cp313-cp313-macosx_11_0_x86_64.whl", hash = "sha256:26f2b3c085fe76e9119e48c1013c1cccdc1f51585d456858290475aa38e7089e", size = 981057, upload-time = "2025-10-24T07:18:31.553Z" }, - { url = "https://files.pythonhosted.org/packages/5c/48/74859073ab276bd0566c719f9ca0108b0cfc1956ca0d68678d117d47d155/lupa-2.6-cp313-cp313-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:60d2f902c7b96fb8ab98493dcff315e7bb4d0b44dc9dd76eb37de575025d5685", size = 1156227, upload-time = "2025-10-24T07:18:33.981Z" }, - { url = "https://files.pythonhosted.org/packages/09/6c/0e9ded061916877253c2266074060eb71ed99fb21d73c8c114a76725bce2/lupa-2.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a02d25dee3a3250967c36590128d9220ae02f2eda166a24279da0b481519cbff", size = 1035752, upload-time = "2025-10-24T07:18:36.32Z" }, - { url = "https://files.pythonhosted.org/packages/dd/ef/f8c32e454ef9f3fe909f6c7d57a39f950996c37a3deb7b391fec7903dab7/lupa-2.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6eae1ee16b886b8914ff292dbefbf2f48abfbdee94b33a88d1d5475e02423203", size = 2069009, upload-time = "2025-10-24T07:18:38.072Z" }, - { url = "https://files.pythonhosted.org/packages/53/dc/15b80c226a5225815a890ee1c11f07968e0aba7a852df41e8ae6fe285063/lupa-2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0edd5073a4ee74ab36f74fe61450148e6044f3952b8d21248581f3c5d1a58be", size = 1056301, upload-time = "2025-10-24T07:18:40.165Z" }, - { url = "https://files.pythonhosted.org/packages/31/14/2086c1425c985acfb30997a67e90c39457122df41324d3c179d6ee2292c6/lupa-2.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0c53ee9f22a8a17e7d4266ad48e86f43771951797042dd51d1494aaa4f5f3f0a", size = 1170673, upload-time = "2025-10-24T07:18:42.426Z" }, - { url = "https://files.pythonhosted.org/packages/10/e5/b216c054cf86576c0191bf9a9f05de6f7e8e07164897d95eea0078dca9b2/lupa-2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:de7c0f157a9064a400d828789191a96da7f4ce889969a588b87ec80de9b14772", size = 2162227, upload-time = "2025-10-24T07:18:46.112Z" }, - { url = "https://files.pythonhosted.org/packages/59/2f/33ecb5bedf4f3bc297ceacb7f016ff951331d352f58e7e791589609ea306/lupa-2.6-cp313-cp313-win32.whl", hash = "sha256:ee9523941ae0a87b5b703417720c5d78f72d2f5bc23883a2ea80a949a3ed9e75", size = 1419558, upload-time = "2025-10-24T07:18:48.371Z" }, - { url = "https://files.pythonhosted.org/packages/f9/b4/55e885834c847ea610e111d87b9ed4768f0afdaeebc00cd46810f25029f6/lupa-2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b1335a5835b0a25ebdbc75cf0bda195e54d133e4d994877ef025e218c2e59db9", size = 1683424, upload-time = "2025-10-24T07:18:50.976Z" }, - { url = "https://files.pythonhosted.org/packages/66/9d/d9427394e54d22a35d1139ef12e845fd700d4872a67a34db32516170b746/lupa-2.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dcb6d0a3264873e1653bc188499f48c1fb4b41a779e315eba45256cfe7bc33c1", size = 953818, upload-time = "2025-10-24T07:18:53.378Z" }, - { url = "https://files.pythonhosted.org/packages/10/41/27bbe81953fb2f9ecfced5d9c99f85b37964cfaf6aa8453bb11283983721/lupa-2.6-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:a37e01f2128f8c36106726cb9d360bac087d58c54b4522b033cc5691c584db18", size = 1915850, upload-time = "2025-10-24T07:18:55.259Z" }, - { url = "https://files.pythonhosted.org/packages/a3/98/f9ff60db84a75ba8725506bbf448fb085bc77868a021998ed2a66d920568/lupa-2.6-cp314-cp314-macosx_11_0_x86_64.whl", hash = "sha256:458bd7e9ff3c150b245b0fcfbb9bd2593d1152ea7f0a7b91c1d185846da033fe", size = 982344, upload-time = "2025-10-24T07:18:57.05Z" }, - { url = "https://files.pythonhosted.org/packages/41/f7/f39e0f1c055c3b887d86b404aaf0ca197b5edfd235a8b81b45b25bac7fc3/lupa-2.6-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:052ee82cac5206a02df77119c325339acbc09f5ce66967f66a2e12a0f3211cad", size = 1156543, upload-time = "2025-10-24T07:18:59.251Z" }, - { url = "https://files.pythonhosted.org/packages/9e/9c/59e6cffa0d672d662ae17bd7ac8ecd2c89c9449dee499e3eb13ca9cd10d9/lupa-2.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96594eca3c87dd07938009e95e591e43d554c1dbd0385be03c100367141db5a8", size = 1047974, upload-time = "2025-10-24T07:19:01.449Z" }, - { url = "https://files.pythonhosted.org/packages/23/c6/a04e9cef7c052717fcb28fb63b3824802488f688391895b618e39be0f684/lupa-2.6-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8faddd9d198688c8884091173a088a8e920ecc96cda2ffed576a23574c4b3f6", size = 2073458, upload-time = "2025-10-24T07:19:03.369Z" }, - { url = "https://files.pythonhosted.org/packages/e6/10/824173d10f38b51fc77785228f01411b6ca28826ce27404c7c912e0e442c/lupa-2.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:daebb3a6b58095c917e76ba727ab37b27477fb926957c825205fbda431552134", size = 1067683, upload-time = "2025-10-24T07:19:06.2Z" }, - { url = "https://files.pythonhosted.org/packages/b6/dc/9692fbcf3c924d9c4ece2d8d2f724451ac2e09af0bd2a782db1cef34e799/lupa-2.6-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f3154e68972befe0f81564e37d8142b5d5d79931a18309226a04ec92487d4ea3", size = 1171892, upload-time = "2025-10-24T07:19:08.544Z" }, - { url = "https://files.pythonhosted.org/packages/84/ff/e318b628d4643c278c96ab3ddea07fc36b075a57383c837f5b11e537ba9d/lupa-2.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e4dadf77b9fedc0bfa53417cc28dc2278a26d4cbd95c29f8927ad4d8fe0a7ef9", size = 2166641, upload-time = "2025-10-24T07:19:10.485Z" }, - { url = "https://files.pythonhosted.org/packages/12/f7/a6f9ec2806cf2d50826980cdb4b3cffc7691dc6f95e13cc728846d5cb793/lupa-2.6-cp314-cp314-win32.whl", hash = "sha256:cb34169c6fa3bab3e8ac58ca21b8a7102f6a94b6a5d08d3636312f3f02fafd8f", size = 1456857, upload-time = "2025-10-24T07:19:37.989Z" }, - { url = "https://files.pythonhosted.org/packages/c5/de/df71896f25bdc18360fdfa3b802cd7d57d7fede41a0e9724a4625b412c85/lupa-2.6-cp314-cp314-win_amd64.whl", hash = "sha256:b74f944fe46c421e25d0f8692aef1e842192f6f7f68034201382ac440ef9ea67", size = 1731191, upload-time = "2025-10-24T07:19:40.281Z" }, - { url = "https://files.pythonhosted.org/packages/47/3c/a1f23b01c54669465f5f4c4083107d496fbe6fb45998771420e9aadcf145/lupa-2.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0e21b716408a21ab65723f8841cf7f2f37a844b7a965eeabb785e27fca4099cf", size = 999343, upload-time = "2025-10-24T07:19:12.519Z" }, - { url = "https://files.pythonhosted.org/packages/c5/6d/501994291cb640bfa2ccf7f554be4e6914afa21c4026bd01bff9ca8aac57/lupa-2.6-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:589db872a141bfff828340079bbdf3e9a31f2689f4ca0d88f97d9e8c2eae6142", size = 2000730, upload-time = "2025-10-24T07:19:14.869Z" }, - { url = "https://files.pythonhosted.org/packages/53/a5/457ffb4f3f20469956c2d4c4842a7675e884efc895b2f23d126d23e126cc/lupa-2.6-cp314-cp314t-macosx_11_0_x86_64.whl", hash = "sha256:cd852a91a4a9d4dcbb9a58100f820a75a425703ec3e3f049055f60b8533b7953", size = 1021553, upload-time = "2025-10-24T07:19:17.123Z" }, - { url = "https://files.pythonhosted.org/packages/51/6b/36bb5a5d0960f2a5c7c700e0819abb76fd9bf9c1d8a66e5106416d6e9b14/lupa-2.6-cp314-cp314t-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:0334753be028358922415ca97a64a3048e4ed155413fc4eaf87dd0a7e2752983", size = 1133275, upload-time = "2025-10-24T07:19:20.51Z" }, - { url = "https://files.pythonhosted.org/packages/19/86/202ff4429f663013f37d2229f6176ca9f83678a50257d70f61a0a97281bf/lupa-2.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:661d895cd38c87658a34780fac54a690ec036ead743e41b74c3fb81a9e65a6aa", size = 1038441, upload-time = "2025-10-24T07:19:22.509Z" }, - { url = "https://files.pythonhosted.org/packages/a7/42/d8125f8e420714e5b52e9c08d88b5329dfb02dcca731b4f21faaee6cc5b5/lupa-2.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aa58454ccc13878cc177c62529a2056be734da16369e451987ff92784994ca7", size = 2058324, upload-time = "2025-10-24T07:19:24.979Z" }, - { url = "https://files.pythonhosted.org/packages/2b/2c/47bf8b84059876e877a339717ddb595a4a7b0e8740bacae78ba527562e1c/lupa-2.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1425017264e470c98022bba8cff5bd46d054a827f5df6b80274f9cc71dafd24f", size = 1060250, upload-time = "2025-10-24T07:19:27.262Z" }, - { url = "https://files.pythonhosted.org/packages/c2/06/d88add2b6406ca1bdec99d11a429222837ca6d03bea42ca75afa169a78cb/lupa-2.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:224af0532d216e3105f0a127410f12320f7c5f1aa0300bdf9646b8d9afb0048c", size = 1151126, upload-time = "2025-10-24T07:19:29.522Z" }, - { url = "https://files.pythonhosted.org/packages/b4/a0/89e6a024c3b4485b89ef86881c9d55e097e7cb0bdb74efb746f2fa6a9a76/lupa-2.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9abb98d5a8fd27c8285302e82199f0e56e463066f88f619d6594a450bf269d80", size = 2153693, upload-time = "2025-10-24T07:19:31.379Z" }, - { url = "https://files.pythonhosted.org/packages/b6/36/a0f007dc58fc1bbf51fb85dcc82fcb1f21b8c4261361de7dab0e3d8521ef/lupa-2.6-cp314-cp314t-win32.whl", hash = "sha256:1849efeba7a8f6fb8aa2c13790bee988fd242ae404bd459509640eeea3d1e291", size = 1590104, upload-time = "2025-10-24T07:19:33.514Z" }, - { url = "https://files.pythonhosted.org/packages/7d/5e/db903ce9cf82c48d6b91bf6d63ae4c8d0d17958939a4e04ba6b9f38b8643/lupa-2.6-cp314-cp314t-win_amd64.whl", hash = "sha256:fc1498d1a4fc028bc521c26d0fad4ca00ed63b952e32fb95949bda76a04bad52", size = 1913818, upload-time = "2025-10-24T07:19:36.039Z" }, -] - [[package]] name = "markdown" version = "3.10.1" @@ -3539,15 +3459,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" }, ] -[[package]] -name = "pathvalidate" -version = "3.3.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fa/2a/52a8da6fe965dea6192eb716b357558e103aea0a1e9a8352ad575a8406ca/pathvalidate-3.3.1.tar.gz", hash = "sha256:b18c07212bfead624345bb8e1d6141cdcf15a39736994ea0b94035ad2b1ba177", size = 63262, upload-time = "2025-06-15T09:07:20.736Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/70/875f4a23bfc4731703a5835487d0d2fb999031bd415e7d17c0ae615c18b7/pathvalidate-3.3.1-py3-none-any.whl", hash = "sha256:5263baab691f8e1af96092fa5137ee17df5bdfbd6cff1fcac4d6ef4bc2e1735f", size = 24305, upload-time = "2025-06-15T09:07:19.117Z" }, -] - [[package]] name = "pillow" version = "12.1.1" @@ -3707,15 +3618,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/22/e7/740997ca82574d03426f897fd88afe3fc8a7306b8c7ea342a8bc1c538488/prek-0.3.2-py3-none-win_arm64.whl", hash = "sha256:9144d176d0daa2469a25c303ef6f6fa95a8df015eb275232f5cb53551ecefef0", size = 4336008, upload-time = "2026-02-06T13:49:52.27Z" }, ] -[[package]] -name = "prometheus-client" -version = "0.24.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f0/58/a794d23feb6b00fc0c72787d7e87d872a6730dd9ed7c7b3e954637d8f280/prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9", size = 85616, upload-time = "2026-01-14T15:26:26.965Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055", size = 64057, upload-time = "2026-01-14T15:26:24.42Z" }, -] - [[package]] name = "prompt-toolkit" version = "3.0.52" @@ -3901,21 +3803,21 @@ argon2 = [ [[package]] name = "py-key-value-aio" -version = "0.3.0" +version = "0.4.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "beartype" }, - { name = "py-key-value-shared" }, + { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/93/ce/3136b771dddf5ac905cc193b461eb67967cf3979688c6696e1f2cdcde7ea/py_key_value_aio-0.3.0.tar.gz", hash = "sha256:858e852fcf6d696d231266da66042d3355a7f9871650415feef9fca7a6cd4155", size = 50801, upload-time = "2025-11-17T16:50:04.711Z" } +sdist = { url = "https://files.pythonhosted.org/packages/04/3c/0397c072a38d4bc580994b42e0c90c5f44f679303489e4376289534735e5/py_key_value_aio-0.4.4.tar.gz", hash = "sha256:e3012e6243ed7cc09bb05457bd4d03b1ba5c2b1ca8700096b3927db79ffbbe55", size = 92300, upload-time = "2026-02-16T21:21:43.245Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/99/10/72f6f213b8f0bce36eff21fda0a13271834e9eeff7f9609b01afdc253c79/py_key_value_aio-0.3.0-py3-none-any.whl", hash = "sha256:1c781915766078bfd608daa769fefb97e65d1d73746a3dfb640460e322071b64", size = 96342, upload-time = "2025-11-17T16:50:03.801Z" }, + { url = "https://files.pythonhosted.org/packages/32/69/f1b537ee70b7def42d63124a539ed3026a11a3ffc3086947a1ca6e861868/py_key_value_aio-0.4.4-py3-none-any.whl", hash = "sha256:18e17564ecae61b987f909fc2cd41ee2012c84b4b1dcb8c055cf8b4bc1bf3f5d", size = 152291, upload-time = "2026-02-16T21:21:44.241Z" }, ] [package.optional-dependencies] -disk = [ - { name = "diskcache" }, - { name = "pathvalidate" }, +filetree = [ + { name = "aiofile" }, + { name = "anyio" }, ] keyring = [ { name = "keyring" }, @@ -3923,22 +3825,6 @@ keyring = [ memory = [ { name = "cachetools" }, ] -redis = [ - { name = "redis" }, -] - -[[package]] -name = "py-key-value-shared" -version = "0.3.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "beartype" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7b/e4/1971dfc4620a3a15b4579fe99e024f5edd6e0967a71154771a059daff4db/py_key_value_shared-0.3.0.tar.gz", hash = "sha256:8fdd786cf96c3e900102945f92aa1473138ebe960ef49da1c833790160c28a4b", size = 11666, upload-time = "2025-11-17T16:50:06.849Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/51/e4/b8b0a03ece72f47dce2307d36e1c34725b7223d209fc679315ffe6a4e2c3/py_key_value_shared-0.3.0-py3-none-any.whl", hash = "sha256:5b0efba7ebca08bb158b1e93afc2f07d30b8f40c2fc12ce24a4c0d84f42f9298", size = 19560, upload-time = "2025-11-17T16:50:05.954Z" }, -] [[package]] name = "pyasn1" @@ -4263,30 +4149,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c1/60/5d4751ba3f4a40a6891f24eec885f51afd78d208498268c734e256fb13c4/pydantic_settings-2.12.0-py3-none-any.whl", hash = "sha256:fddb9fd99a5b18da837b29710391e945b1e30c135477f484084ee513adb93809", size = 51880, upload-time = "2025-11-10T14:25:45.546Z" }, ] -[[package]] -name = "pydocket" -version = "0.17.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cloudpickle" }, - { name = "croniter" }, - { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, - { name = "fakeredis", extra = ["lua"] }, - { name = "opentelemetry-api" }, - { name = "prometheus-client" }, - { name = "py-key-value-aio", extra = ["memory", "redis"] }, - { name = "python-json-logger" }, - { name = "redis" }, - { name = "rich" }, - { name = "taskgroup", marker = "python_full_version < '3.11'" }, - { name = "typer" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/73/26/ac23ead3725475468b50b486939bf5feda27180050a614a7407344a0af0e/pydocket-0.17.5.tar.gz", hash = "sha256:19a6976d8fd11c1acf62feb0291a339e06beaefa100f73dd38c6499760ad3e62", size = 334829, upload-time = "2026-01-30T18:44:39.702Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/14/98/73427d065c067a99de6afbe24df3d90cf20d63152ceb42edff2b6e829d4c/pydocket-0.17.5-py3-none-any.whl", hash = "sha256:544d7c2625a33e52528ac24db25794841427dfc2cf30b9c558ac387c77746241", size = 93355, upload-time = "2026-01-30T18:44:37.972Z" }, -] - [[package]] name = "pyee" version = "13.0.0" @@ -4517,15 +4379,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" }, ] -[[package]] -name = "python-json-logger" -version = "4.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/29/bf/eca6a3d43db1dae7070f70e160ab20b807627ba953663ba07928cdd3dc58/python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f", size = 17683, upload-time = "2025-10-06T04:15:18.984Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2", size = 15548, upload-time = "2025-10-06T04:15:17.553Z" }, -] - [[package]] name = "python-multipart" version = "0.0.22" @@ -4586,15 +4439,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c6/78/397db326746f0a342855b81216ae1f0a32965deccfd7c830a2dbc66d2483/pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de", size = 13729, upload-time = "2026-01-30T01:03:45.029Z" }, ] -[[package]] -name = "pytz" -version = "2025.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, -] - [[package]] name = "pywin32" version = "311" @@ -4711,18 +4555,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/aa/96/7935186fba032312eb8a75e6503440b0e6de76c901421f791408e4debd93/rcslice-1.1.0-py3-none-any.whl", hash = "sha256:1b12fc0c0ca452e8a9fd2b56ac008162f19e250906a4290a7e7a98be3200c2a6", size = 5180, upload-time = "2018-09-27T12:44:05.197Z" }, ] -[[package]] -name = "redis" -version = "7.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "async-timeout", marker = "python_full_version < '3.11.3'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/43/c8/983d5c6579a411d8a99bc5823cc5712768859b5ce2c8afe1a65b37832c81/redis-7.1.0.tar.gz", hash = "sha256:b1cc3cfa5a2cb9c2ab3ba700864fb0ad75617b41f01352ce5779dabf6d5f9c3c", size = 4796669, upload-time = "2025-11-19T15:54:39.961Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/89/f0/8956f8a86b20d7bb9d6ac0187cf4cd54d8065bc9a1a09eb8011d4d326596/redis-7.1.0-py3-none-any.whl", hash = "sha256:23c52b208f92b56103e17c5d06bdc1a6c2c0b3106583985a76a18f83b265de2b", size = 354159, upload-time = "2025-11-19T15:54:38.064Z" }, -] - [[package]] name = "referencing" version = "0.36.2" @@ -5412,19 +5244,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/17/43/47c7cf84b3bd74a8631b02d47db356656bb8dff6f2e61a4c749963814d0d/super_collections-0.6.2-py3-none-any.whl", hash = "sha256:291b74d26299e9051d69ad9d89e61b07b6646f86a57a2f5ab3063d206eee9c56", size = 16173, upload-time = "2025-09-30T00:37:07.104Z" }, ] -[[package]] -name = "taskgroup" -version = "0.2.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "exceptiongroup", marker = "python_full_version < '3.14'" }, - { name = "typing-extensions", marker = "python_full_version < '3.14'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f0/8d/e218e0160cc1b692e6e0e5ba34e8865dbb171efeb5fc9a704544b3020605/taskgroup-0.2.2.tar.gz", hash = "sha256:078483ac3e78f2e3f973e2edbf6941374fbea81b9c5d0a96f51d297717f4752d", size = 11504, upload-time = "2025-01-03T09:24:13.761Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/b1/74babcc824a57904e919f3af16d86c08b524c0691504baf038ef2d7f655c/taskgroup-0.2.2-py2.py3-none-any.whl", hash = "sha256:e2c53121609f4ae97303e9ea1524304b4de6faf9eb2c9280c7f87976479a52fb", size = 14237, upload-time = "2025-01-03T09:24:11.41Z" }, -] - [[package]] name = "temporalio" version = "1.20.0" @@ -5856,6 +5675,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e3/7a/92047d32bf6f2d9db64605fc32e8eb0e0dd68b671eaafc12a464f69c4af4/ujson-5.12.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:ab9056d94e5db513d9313b34394f3a3b83e6301a581c28ad67773434f3faccab", size = 44053, upload-time = "2026-03-11T22:19:23.918Z" }, ] +[[package]] +name = "uncalled-for" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/02/7c/b5b7d8136f872e3f13b0584e576886de0489d7213a12de6bebf29ff6ebfc/uncalled_for-0.2.0.tar.gz", hash = "sha256:b4f8fdbcec328c5a113807d653e041c5094473dd4afa7c34599ace69ccb7e69f", size = 49488, upload-time = "2026-02-27T17:40:58.137Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ff/7f/4320d9ce3be404e6310b915c3629fe27bf1e2f438a1a7a3cb0396e32e9a9/uncalled_for-0.2.0-py3-none-any.whl", hash = "sha256:2c0bd338faff5f930918f79e7eb9ff48290df2cb05fcc0b40a7f334e55d4d85f", size = 11351, upload-time = "2026-02-27T17:40:56.804Z" }, +] + [[package]] name = "urllib3" version = "2.6.3" From 681146d90b5534d6139668ac240c7bff63e4a7bc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Apr 2026 07:33:52 +0000 Subject: [PATCH 39/69] =?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 ea26953fa3..b0914ca1f9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* ⬆ Bump fastmcp from 2.14.5 to 3.2.0. PR [#15267](https://github.com/fastapi/fastapi/pull/15267) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Contributors and Translators. PR [#15270](https://github.com/fastapi/fastapi/pull/15270) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump requests from 2.32.5 to 2.33.0. PR [#15228](https://github.com/fastapi/fastapi/pull/15228) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👷 Add ty check to `lint.sh`. PR [#15136](https://github.com/fastapi/fastapi/pull/15136) by [@svlandeg](https://github.com/svlandeg). From 9274097c302071f8506808c0c2faf1e4393fbb5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Apr 2026 14:36:41 +0200 Subject: [PATCH 40/69] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20GitHub?= =?UTF-8?q?=20topic=20repositories=20(#15274)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/data/topic_repos.yml | 364 +++++++++++++++++------------------ 1 file changed, 182 insertions(+), 182 deletions(-) diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index 693d08ffd5..9703c7a6bb 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,298 +1,303 @@ - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 41789 + stars: 42397 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 34587 + stars: 34997 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21835 + stars: 21857 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 20755 + stars: 20868 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin - name: sqlmodel html_url: https://github.com/fastapi/sqlmodel - stars: 17687 + stars: 17770 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 16611 + stars: 16897 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov - name: Douyin_TikTok_Download_API html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API - stars: 16474 + stars: 16878 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal - name: SurfSense html_url: https://github.com/MODSetter/SurfSense - stars: 13069 + stars: 13614 owner_login: MODSetter owner_html_url: https://github.com/MODSetter - name: machine-learning-zoomcamp html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp - stars: 12674 + stars: 12780 owner_login: DataTalksClub owner_html_url: https://github.com/DataTalksClub - name: fastapi_mcp html_url: https://github.com/tadata-org/fastapi_mcp - stars: 11604 + stars: 11752 owner_login: tadata-org owner_html_url: https://github.com/tadata-org - name: awesome-fastapi html_url: https://github.com/mjhea0/awesome-fastapi - stars: 11119 + stars: 11203 owner_login: mjhea0 owner_html_url: https://github.com/mjhea0 - name: XHS-Downloader html_url: https://github.com/JoeanAmier/XHS-Downloader - stars: 10206 + stars: 10612 owner_login: JoeanAmier owner_html_url: https://github.com/JoeanAmier - name: polar html_url: https://github.com/polarsource/polar - stars: 9500 + stars: 9626 owner_login: polarsource owner_html_url: https://github.com/polarsource - name: FastUI html_url: https://github.com/pydantic/FastUI - stars: 8956 + stars: 8958 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: FileCodeBox html_url: https://github.com/vastsa/FileCodeBox - stars: 8128 + stars: 8191 owner_login: vastsa owner_html_url: https://github.com/vastsa - name: nonebot2 html_url: https://github.com/nonebot/nonebot2 - stars: 7384 + stars: 7456 owner_login: nonebot owner_html_url: https://github.com/nonebot - name: hatchet html_url: https://github.com/hatchet-dev/hatchet - stars: 6659 + stars: 6784 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: 6024 + stars: 6064 owner_login: fastapi-users owner_html_url: https://github.com/fastapi-users - name: serge html_url: https://github.com/serge-chat/serge - stars: 5746 + stars: 5738 owner_login: serge-chat owner_html_url: https://github.com/serge-chat +- name: Yuxi + html_url: https://github.com/xerrors/Yuxi + stars: 4761 + owner_login: xerrors + owner_html_url: https://github.com/xerrors +- name: Kokoro-FastAPI + html_url: https://github.com/remsky/Kokoro-FastAPI + stars: 4649 + owner_login: remsky + owner_html_url: https://github.com/remsky - name: strawberry html_url: https://github.com/strawberry-graphql/strawberry - stars: 4616 + stars: 4636 owner_login: strawberry-graphql owner_html_url: https://github.com/strawberry-graphql - name: devpush html_url: https://github.com/hunvreus/devpush - stars: 4515 + stars: 4589 owner_login: hunvreus owner_html_url: https://github.com/hunvreus -- name: Kokoro-FastAPI - html_url: https://github.com/remsky/Kokoro-FastAPI - stars: 4494 - owner_login: remsky - owner_html_url: https://github.com/remsky -- name: Yuxi-Know - html_url: https://github.com/xerrors/Yuxi-Know - stars: 4404 - owner_login: xerrors - owner_html_url: https://github.com/xerrors - name: poem html_url: https://github.com/poem-web/poem - stars: 4359 + stars: 4375 owner_login: poem-web owner_html_url: https://github.com/poem-web -- name: chatgpt-web-share - html_url: https://github.com/chatpire/chatgpt-web-share - stars: 4274 - owner_login: chatpire - owner_html_url: https://github.com/chatpire - name: dynaconf html_url: https://github.com/dynaconf/dynaconf - stars: 4266 + stars: 4276 owner_login: dynaconf owner_html_url: https://github.com/dynaconf -- name: atrilabs-engine - html_url: https://github.com/Atri-Labs/atrilabs-engine - stars: 4085 - owner_login: Atri-Labs - owner_html_url: https://github.com/Atri-Labs +- name: chatgpt-web-share + html_url: https://github.com/chatpire/chatgpt-web-share + stars: 4272 + owner_login: chatpire + owner_html_url: https://github.com/chatpire - name: logfire html_url: https://github.com/pydantic/logfire - stars: 4050 + stars: 4145 owner_login: pydantic owner_html_url: https://github.com/pydantic +- name: atrilabs-engine + html_url: https://github.com/Atri-Labs/atrilabs-engine + stars: 4086 + owner_login: Atri-Labs + owner_html_url: https://github.com/Atri-Labs - name: huma html_url: https://github.com/danielgtaylor/huma - stars: 3848 + stars: 3933 owner_login: danielgtaylor owner_html_url: https://github.com/danielgtaylor - name: LitServe html_url: https://github.com/Lightning-AI/LitServe - stars: 3803 + stars: 3851 owner_login: Lightning-AI owner_html_url: https://github.com/Lightning-AI - name: datamodel-code-generator html_url: https://github.com/koxudaxi/datamodel-code-generator - stars: 3785 + stars: 3839 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi - name: fastapi-admin html_url: https://github.com/fastapi-admin/fastapi-admin - stars: 3717 + stars: 3745 owner_login: fastapi-admin owner_html_url: https://github.com/fastapi-admin -- name: farfalle - html_url: https://github.com/rashadphz/farfalle - stars: 3515 - owner_login: rashadphz - owner_html_url: https://github.com/rashadphz - name: tracecat html_url: https://github.com/TracecatHQ/tracecat - stars: 3498 + stars: 3542 owner_login: TracecatHQ owner_html_url: https://github.com/TracecatHQ +- name: farfalle + html_url: https://github.com/rashadphz/farfalle + stars: 3521 + owner_login: rashadphz + owner_html_url: https://github.com/rashadphz - name: mcp-context-forge html_url: https://github.com/IBM/mcp-context-forge - stars: 3347 + stars: 3501 owner_login: IBM owner_html_url: https://github.com/IBM - name: opyrator html_url: https://github.com/ml-tooling/opyrator - stars: 3139 + stars: 3137 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling - name: docarray html_url: https://github.com/docarray/docarray - stars: 3116 + stars: 3120 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: 3079 + stars: 3092 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: 2908 + stars: 2913 owner_login: tiangolo owner_html_url: https://github.com/tiangolo - name: FastAPI-template html_url: https://github.com/s3rius/FastAPI-template - stars: 2749 + stars: 2768 owner_login: s3rius owner_html_url: https://github.com/s3rius - name: best-of-web-python html_url: https://github.com/ml-tooling/best-of-web-python - stars: 2695 + stars: 2703 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling - name: sqladmin - html_url: https://github.com/aminalaee/sqladmin - stars: 2674 - owner_login: aminalaee - owner_html_url: https://github.com/aminalaee + html_url: https://github.com/smithyhq/sqladmin + stars: 2696 + owner_login: smithyhq + owner_html_url: https://github.com/smithyhq - name: YC-Killer html_url: https://github.com/sahibzada-allahyar/YC-Killer - stars: 2665 + stars: 2675 owner_login: sahibzada-allahyar owner_html_url: https://github.com/sahibzada-allahyar - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react - stars: 2585 + stars: 2579 owner_login: Buuntu owner_html_url: https://github.com/Buuntu +- name: supabase-py + html_url: https://github.com/supabase/supabase-py + stars: 2486 + owner_login: supabase + owner_html_url: https://github.com/supabase - name: RasaGPT html_url: https://github.com/paulpierre/RasaGPT stars: 2462 owner_login: paulpierre owner_html_url: https://github.com/paulpierre -- name: supabase-py - html_url: https://github.com/supabase/supabase-py - stars: 2452 - owner_login: supabase - owner_html_url: https://github.com/supabase - name: 30-Days-of-Python html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python - stars: 2435 + stars: 2450 owner_login: codingforentrepreneurs owner_html_url: https://github.com/codingforentrepreneurs - name: NoteDiscovery html_url: https://github.com/gamosoft/NoteDiscovery - stars: 2354 + stars: 2400 owner_login: gamosoft owner_html_url: https://github.com/gamosoft - name: nextpy html_url: https://github.com/dot-agent/nextpy - stars: 2335 + stars: 2339 owner_login: dot-agent owner_html_url: https://github.com/dot-agent - name: fastapi-utils html_url: https://github.com/fastapiutils/fastapi-utils - stars: 2306 + stars: 2308 owner_login: fastapiutils owner_html_url: https://github.com/fastapiutils - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 2276 + stars: 2300 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai - name: solara html_url: https://github.com/widgetti/solara - stars: 2154 + stars: 2156 owner_login: widgetti owner_html_url: https://github.com/widgetti +- name: fastapi-best-architecture + html_url: https://github.com/fastapi-practices/fastapi-best-architecture + stars: 2148 + owner_login: fastapi-practices + owner_html_url: https://github.com/fastapi-practices +- name: fastapi-langgraph-agent-production-ready-template + html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template + stars: 2103 + owner_login: wassim249 + owner_html_url: https://github.com/wassim249 - name: mangum html_url: https://github.com/Kludex/mangum - stars: 2084 + stars: 2100 owner_login: Kludex owner_html_url: https://github.com/Kludex -- name: fastapi_best_architecture - html_url: https://github.com/fastapi-practices/fastapi_best_architecture - stars: 2083 - owner_login: fastapi-practices - owner_html_url: https://github.com/fastapi-practices - name: vue-fastapi-admin html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 2012 + stars: 2059 owner_login: mizhexiaoxiao owner_html_url: https://github.com/mizhexiaoxiao -- name: fastapi-langgraph-agent-production-ready-template - html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template - stars: 2006 - owner_login: wassim249 - owner_html_url: https://github.com/wassim249 - name: agentkit html_url: https://github.com/BCG-X-Official/agentkit - stars: 1946 + stars: 1947 owner_login: BCG-X-Official owner_html_url: https://github.com/BCG-X-Official - name: slowapi html_url: https://github.com/laurentS/slowapi - stars: 1924 + stars: 1946 owner_login: laurentS owner_html_url: https://github.com/laurentS - name: openapi-python-client html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1915 + stars: 1930 owner_login: openapi-generators owner_html_url: https://github.com/openapi-generators +- name: xhs_ai_publisher + html_url: https://github.com/BetaStreetOmnis/xhs_ai_publisher + stars: 1904 + owner_login: BetaStreetOmnis + owner_html_url: https://github.com/BetaStreetOmnis - name: manage-fastapi html_url: https://github.com/ycd/manage-fastapi stars: 1898 @@ -300,57 +305,57 @@ owner_html_url: https://github.com/ycd - name: piccolo html_url: https://github.com/piccolo-orm/piccolo - stars: 1864 + stars: 1876 owner_login: piccolo-orm owner_html_url: https://github.com/piccolo-orm -- name: fastapi-cache - html_url: https://github.com/long2ice/fastapi-cache - stars: 1837 - owner_login: long2ice - owner_html_url: https://github.com/long2ice - name: FastAPI-boilerplate html_url: https://github.com/benavlabs/FastAPI-boilerplate - stars: 1820 + stars: 1859 owner_login: benavlabs owner_html_url: https://github.com/benavlabs +- name: fastapi-cache + html_url: https://github.com/long2ice/fastapi-cache + stars: 1853 + owner_login: long2ice + owner_html_url: https://github.com/long2ice - name: python-week-2022 html_url: https://github.com/rochacbruno/python-week-2022 - stars: 1811 + stars: 1809 owner_login: rochacbruno owner_html_url: https://github.com/rochacbruno - name: ormar html_url: https://github.com/ormar-orm/ormar - stars: 1801 + stars: 1808 owner_login: ormar-orm owner_html_url: https://github.com/ormar-orm - name: termpair html_url: https://github.com/cs01/termpair - stars: 1728 + stars: 1730 owner_login: cs01 owner_html_url: https://github.com/cs01 - name: fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1682 + stars: 1683 owner_login: awtkns owner_html_url: https://github.com/awtkns -- name: langchain-serve - html_url: https://github.com/jina-ai/langchain-serve - stars: 1633 - owner_login: jina-ai - owner_html_url: https://github.com/jina-ai - name: fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1631 + stars: 1638 owner_login: uriyyo owner_html_url: https://github.com/uriyyo - name: bracket html_url: https://github.com/evroon/bracket - stars: 1619 + stars: 1638 owner_login: evroon owner_html_url: https://github.com/evroon +- name: langchain-serve + html_url: https://github.com/jina-ai/langchain-serve + stars: 1634 + owner_login: jina-ai + owner_html_url: https://github.com/jina-ai - name: awesome-fastapi-projects html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1596 + stars: 1597 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: coronavirus-tracker-api @@ -358,138 +363,133 @@ stars: 1568 owner_login: ExpDev07 owner_html_url: https://github.com/ExpDev07 +- name: WebRPA + html_url: https://github.com/pmh1314520/WebRPA + stars: 1532 + owner_login: pmh1314520 + owner_html_url: https://github.com/pmh1314520 - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1520 + stars: 1527 owner_login: amisadmin owner_html_url: https://github.com/amisadmin - name: fastcrud html_url: https://github.com/benavlabs/fastcrud - stars: 1487 + stars: 1506 owner_login: benavlabs owner_html_url: https://github.com/benavlabs - name: fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1465 + stars: 1482 owner_login: teamhide owner_html_url: https://github.com/teamhide - name: awesome-python-resources html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1441 + stars: 1444 owner_login: DjangoEx owner_html_url: https://github.com/DjangoEx - name: prometheus-fastapi-instrumentator html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1433 + stars: 1438 owner_login: trallnag owner_html_url: https://github.com/trallnag +- name: honcho + html_url: https://github.com/plastic-labs/honcho + stars: 1419 + owner_login: plastic-labs + owner_html_url: https://github.com/plastic-labs +- name: tavily-key-generator + html_url: https://github.com/skernelx/tavily-key-generator + stars: 1416 + owner_login: skernelx + owner_html_url: https://github.com/skernelx +- name: fastapi-tutorial + html_url: https://github.com/liaogx/fastapi-tutorial + stars: 1384 + owner_login: liaogx + owner_html_url: https://github.com/liaogx - name: fastapi-code-generator html_url: https://github.com/koxudaxi/fastapi-code-generator stars: 1384 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi -- name: fastapi-tutorial - html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1365 - owner_login: liaogx - owner_html_url: https://github.com/liaogx -- name: WebRPA - html_url: https://github.com/pmh1314520/WebRPA - stars: 1354 - owner_login: pmh1314520 - owner_html_url: https://github.com/pmh1314520 - name: budgetml html_url: https://github.com/ebhy/budgetml - stars: 1344 + stars: 1346 owner_login: ebhy owner_html_url: https://github.com/ebhy -- name: fastapi-scaff - html_url: https://github.com/atpuxiner/fastapi-scaff - stars: 1305 - owner_login: atpuxiner - owner_html_url: https://github.com/atpuxiner - name: bolt-python html_url: https://github.com/slackapi/bolt-python - stars: 1278 + stars: 1286 owner_login: slackapi owner_html_url: https://github.com/slackapi +- name: aktools + html_url: https://github.com/akfamily/aktools + stars: 1283 + owner_login: akfamily + owner_html_url: https://github.com/akfamily - name: bedrock-chat html_url: https://github.com/aws-samples/bedrock-chat - stars: 1271 + stars: 1282 owner_login: aws-samples owner_html_url: https://github.com/aws-samples +- name: fastapi-scaff + html_url: https://github.com/atpuxiner/fastapi-scaff + stars: 1275 + owner_login: atpuxiner + owner_html_url: https://github.com/atpuxiner - name: fastapi-alembic-sqlmodel-async html_url: https://github.com/vargasjona/fastapi-alembic-sqlmodel-async - stars: 1269 + stars: 1267 owner_login: vargasjona owner_html_url: https://github.com/vargasjona -- name: fastapi_production_template - html_url: https://github.com/zhanymkanov/fastapi_production_template - stars: 1231 - owner_login: zhanymkanov - owner_html_url: https://github.com/zhanymkanov - name: restish html_url: https://github.com/rest-sh/restish - stars: 1225 + stars: 1258 owner_login: rest-sh owner_html_url: https://github.com/rest-sh -- name: aktools - html_url: https://github.com/akfamily/aktools - stars: 1223 - owner_login: akfamily - owner_html_url: https://github.com/akfamily - name: RuoYi-Vue3-FastAPI html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI - stars: 1202 + stars: 1248 owner_login: insistence owner_html_url: https://github.com/insistence +- name: fastapi_production_template + html_url: https://github.com/zhanymkanov/fastapi_production_template + stars: 1240 + owner_login: zhanymkanov + owner_html_url: https://github.com/zhanymkanov - name: langchain-extract html_url: https://github.com/langchain-ai/langchain-extract - stars: 1189 + stars: 1193 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai +- name: open-wearables + html_url: https://github.com/the-momentum/open-wearables + stars: 1170 + owner_login: the-momentum + owner_html_url: https://github.com/the-momentum - name: odmantic html_url: https://github.com/art049/odmantic - stars: 1167 + stars: 1168 owner_login: art049 owner_html_url: https://github.com/art049 - name: authx html_url: https://github.com/yezz123/authx - stars: 1144 + stars: 1160 owner_login: yezz123 owner_html_url: https://github.com/yezz123 -- name: enterprise-deep-research - html_url: https://github.com/SalesforceAIResearch/enterprise-deep-research - stars: 1123 - owner_login: SalesforceAIResearch - owner_html_url: https://github.com/SalesforceAIResearch -- name: SAG - html_url: https://github.com/Zleap-AI/SAG - stars: 1115 - owner_login: Zleap-AI - owner_html_url: https://github.com/Zleap-AI - name: FileSync html_url: https://github.com/polius/FileSync - stars: 1111 + stars: 1153 owner_login: polius owner_html_url: https://github.com/polius -- name: every-pdf - html_url: https://github.com/DDULDDUCK/every-pdf - stars: 1093 - owner_login: DDULDDUCK - owner_html_url: https://github.com/DDULDDUCK -- name: fastapi-observability - html_url: https://github.com/blueswen/fastapi-observability - stars: 1079 - owner_login: blueswen - owner_html_url: https://github.com/blueswen -- name: flock - html_url: https://github.com/Onelevenvy/flock - stars: 1073 - owner_login: Onelevenvy - owner_html_url: https://github.com/Onelevenvy -- name: titiler - html_url: https://github.com/developmentseed/titiler - stars: 1060 - owner_login: developmentseed - owner_html_url: https://github.com/developmentseed +- name: enterprise-deep-research + html_url: https://github.com/SalesforceAIResearch/enterprise-deep-research + stars: 1150 + owner_login: SalesforceAIResearch + owner_html_url: https://github.com/SalesforceAIResearch +- name: yubal + html_url: https://github.com/guillevc/yubal + stars: 1135 + owner_login: guillevc + owner_html_url: https://github.com/guillevc From cc477965097d1cbb780fae7b731e43132fe75890 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Apr 2026 12:37:11 +0000 Subject: [PATCH 41/69] =?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 b0914ca1f9..c072002af4 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 [#15274](https://github.com/fastapi/fastapi/pull/15274) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump fastmcp from 2.14.5 to 3.2.0. PR [#15267](https://github.com/fastapi/fastapi/pull/15267) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Contributors and Translators. PR [#15270](https://github.com/fastapi/fastapi/pull/15270) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump requests from 2.32.5 to 2.33.0. PR [#15228](https://github.com/fastapi/fastapi/pull/15228) by [@dependabot[bot]](https://github.com/apps/dependabot). From 5599c59b9e7112109f04b63a58034fb95833f514 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:27:20 +0200 Subject: [PATCH 42/69] =?UTF-8?q?=E2=AC=86=20Bump=20ruff=20from=200.15.0?= =?UTF-8?q?=20to=200.15.8=20(#15277)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/uv.lock b/uv.lock index 8fd075b526..67dc875858 100644 --- a/uv.lock +++ b/uv.lock @@ -5002,27 +5002,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.15.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c8/39/5cee96809fbca590abea6b46c6d1c586b49663d1d2830a751cc8fc42c666/ruff-0.15.0.tar.gz", hash = "sha256:6bdea47cdbea30d40f8f8d7d69c0854ba7c15420ec75a26f463290949d7f7e9a", size = 4524893, upload-time = "2026-02-03T17:53:35.357Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bc/88/3fd1b0aa4b6330d6aaa63a285bc96c9f71970351579152d231ed90914586/ruff-0.15.0-py3-none-linux_armv6l.whl", hash = "sha256:aac4ebaa612a82b23d45964586f24ae9bc23ca101919f5590bdb368d74ad5455", size = 10354332, upload-time = "2026-02-03T17:52:54.892Z" }, - { url = "https://files.pythonhosted.org/packages/72/f6/62e173fbb7eb75cc29fe2576a1e20f0a46f671a2587b5f604bfb0eaf5f6f/ruff-0.15.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:dcd4be7cc75cfbbca24a98d04d0b9b36a270d0833241f776b788d59f4142b14d", size = 10767189, upload-time = "2026-02-03T17:53:19.778Z" }, - { url = "https://files.pythonhosted.org/packages/99/e4/968ae17b676d1d2ff101d56dc69cf333e3a4c985e1ec23803df84fc7bf9e/ruff-0.15.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d747e3319b2bce179c7c1eaad3d884dc0a199b5f4d5187620530adf9105268ce", size = 10075384, upload-time = "2026-02-03T17:53:29.241Z" }, - { url = "https://files.pythonhosted.org/packages/a2/bf/9843c6044ab9e20af879c751487e61333ca79a2c8c3058b15722386b8cae/ruff-0.15.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:650bd9c56ae03102c51a5e4b554d74d825ff3abe4db22b90fd32d816c2e90621", size = 10481363, upload-time = "2026-02-03T17:52:43.332Z" }, - { url = "https://files.pythonhosted.org/packages/55/d9/4ada5ccf4cd1f532db1c8d44b6f664f2208d3d93acbeec18f82315e15193/ruff-0.15.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6664b7eac559e3048223a2da77769c2f92b43a6dfd4720cef42654299a599c9", size = 10187736, upload-time = "2026-02-03T17:53:00.522Z" }, - { url = "https://files.pythonhosted.org/packages/86/e2/f25eaecd446af7bb132af0a1d5b135a62971a41f5366ff41d06d25e77a91/ruff-0.15.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f811f97b0f092b35320d1556f3353bf238763420ade5d9e62ebd2b73f2ff179", size = 10968415, upload-time = "2026-02-03T17:53:15.705Z" }, - { url = "https://files.pythonhosted.org/packages/e7/dc/f06a8558d06333bf79b497d29a50c3a673d9251214e0d7ec78f90b30aa79/ruff-0.15.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:761ec0a66680fab6454236635a39abaf14198818c8cdf691e036f4bc0f406b2d", size = 11809643, upload-time = "2026-02-03T17:53:23.031Z" }, - { url = "https://files.pythonhosted.org/packages/dd/45/0ece8db2c474ad7df13af3a6d50f76e22a09d078af63078f005057ca59eb/ruff-0.15.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:940f11c2604d317e797b289f4f9f3fa5555ffe4fb574b55ed006c3d9b6f0eb78", size = 11234787, upload-time = "2026-02-03T17:52:46.432Z" }, - { url = "https://files.pythonhosted.org/packages/8a/d9/0e3a81467a120fd265658d127db648e4d3acfe3e4f6f5d4ea79fac47e587/ruff-0.15.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcbca3d40558789126da91d7ef9a7c87772ee107033db7191edefa34e2c7f1b4", size = 11112797, upload-time = "2026-02-03T17:52:49.274Z" }, - { url = "https://files.pythonhosted.org/packages/b2/cb/8c0b3b0c692683f8ff31351dfb6241047fa873a4481a76df4335a8bff716/ruff-0.15.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9a121a96db1d75fa3eb39c4539e607f628920dd72ff1f7c5ee4f1b768ac62d6e", size = 11033133, upload-time = "2026-02-03T17:53:33.105Z" }, - { url = "https://files.pythonhosted.org/packages/f8/5e/23b87370cf0f9081a8c89a753e69a4e8778805b8802ccfe175cc410e50b9/ruff-0.15.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5298d518e493061f2eabd4abd067c7e4fb89e2f63291c94332e35631c07c3662", size = 10442646, upload-time = "2026-02-03T17:53:06.278Z" }, - { url = "https://files.pythonhosted.org/packages/e1/9a/3c94de5ce642830167e6d00b5c75aacd73e6347b4c7fc6828699b150a5ee/ruff-0.15.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:afb6e603d6375ff0d6b0cee563fa21ab570fd15e65c852cb24922cef25050cf1", size = 10195750, upload-time = "2026-02-03T17:53:26.084Z" }, - { url = "https://files.pythonhosted.org/packages/30/15/e396325080d600b436acc970848d69df9c13977942fb62bb8722d729bee8/ruff-0.15.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:77e515f6b15f828b94dc17d2b4ace334c9ddb7d9468c54b2f9ed2b9c1593ef16", size = 10676120, upload-time = "2026-02-03T17:53:09.363Z" }, - { url = "https://files.pythonhosted.org/packages/8d/c9/229a23d52a2983de1ad0fb0ee37d36e0257e6f28bfd6b498ee2c76361874/ruff-0.15.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:6f6e80850a01eb13b3e42ee0ebdf6e4497151b48c35051aab51c101266d187a3", size = 11201636, upload-time = "2026-02-03T17:52:57.281Z" }, - { url = "https://files.pythonhosted.org/packages/6f/b0/69adf22f4e24f3677208adb715c578266842e6e6a3cc77483f48dd999ede/ruff-0.15.0-py3-none-win32.whl", hash = "sha256:238a717ef803e501b6d51e0bdd0d2c6e8513fe9eec14002445134d3907cd46c3", size = 10465945, upload-time = "2026-02-03T17:53:12.591Z" }, - { url = "https://files.pythonhosted.org/packages/51/ad/f813b6e2c97e9b4598be25e94a9147b9af7e60523b0cb5d94d307c15229d/ruff-0.15.0-py3-none-win_amd64.whl", hash = "sha256:dd5e4d3301dc01de614da3cdffc33d4b1b96fb89e45721f1598e5532ccf78b18", size = 11564657, upload-time = "2026-02-03T17:52:51.893Z" }, - { url = "https://files.pythonhosted.org/packages/f6/b0/2d823f6e77ebe560f4e397d078487e8d52c1516b331e3521bc75db4272ca/ruff-0.15.0-py3-none-win_arm64.whl", hash = "sha256:c480d632cc0ca3f0727acac8b7d053542d9e114a462a145d0b00e7cd658c515a", size = 10865753, upload-time = "2026-02-03T17:53:03.014Z" }, +version = "0.15.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/14/b0/73cf7550861e2b4824950b8b52eebdcc5adc792a00c514406556c5b80817/ruff-0.15.8.tar.gz", hash = "sha256:995f11f63597ee362130d1d5a327a87cb6f3f5eae3094c620bcc632329a4d26e", size = 4610921, upload-time = "2026-03-26T18:39:38.675Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/92/c445b0cd6da6e7ae51e954939cb69f97e008dbe750cfca89b8cedc081be7/ruff-0.15.8-py3-none-linux_armv6l.whl", hash = "sha256:cbe05adeba76d58162762d6b239c9056f1a15a55bd4b346cfd21e26cd6ad7bc7", size = 10527394, upload-time = "2026-03-26T18:39:41.566Z" }, + { url = "https://files.pythonhosted.org/packages/eb/92/f1c662784d149ad1414cae450b082cf736430c12ca78367f20f5ed569d65/ruff-0.15.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d3e3d0b6ba8dca1b7ef9ab80a28e840a20070c4b62e56d675c24f366ef330570", size = 10905693, upload-time = "2026-03-26T18:39:30.364Z" }, + { url = "https://files.pythonhosted.org/packages/ca/f2/7a631a8af6d88bcef997eb1bf87cc3da158294c57044aafd3e17030613de/ruff-0.15.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ee3ae5c65a42f273f126686353f2e08ff29927b7b7e203b711514370d500de3", size = 10323044, upload-time = "2026-03-26T18:39:33.37Z" }, + { url = "https://files.pythonhosted.org/packages/67/18/1bf38e20914a05e72ef3b9569b1d5c70a7ef26cd188d69e9ca8ef588d5bf/ruff-0.15.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdce027ada77baa448077ccc6ebb2fa9c3c62fd110d8659d601cf2f475858d94", size = 10629135, upload-time = "2026-03-26T18:39:44.142Z" }, + { url = "https://files.pythonhosted.org/packages/d2/e9/138c150ff9af60556121623d41aba18b7b57d95ac032e177b6a53789d279/ruff-0.15.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:12e617fc01a95e5821648a6df341d80456bd627bfab8a829f7cfc26a14a4b4a3", size = 10348041, upload-time = "2026-03-26T18:39:52.178Z" }, + { url = "https://files.pythonhosted.org/packages/02/f1/5bfb9298d9c323f842c5ddeb85f1f10ef51516ac7a34ba446c9347d898df/ruff-0.15.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:432701303b26416d22ba696c39f2c6f12499b89093b61360abc34bcc9bf07762", size = 11121987, upload-time = "2026-03-26T18:39:55.195Z" }, + { url = "https://files.pythonhosted.org/packages/10/11/6da2e538704e753c04e8d86b1fc55712fdbdcc266af1a1ece7a51fff0d10/ruff-0.15.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d910ae974b7a06a33a057cb87d2a10792a3b2b3b35e33d2699fdf63ec8f6b17a", size = 11951057, upload-time = "2026-03-26T18:39:19.18Z" }, + { url = "https://files.pythonhosted.org/packages/83/f0/c9208c5fd5101bf87002fed774ff25a96eea313d305f1e5d5744698dc314/ruff-0.15.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2033f963c43949d51e6fdccd3946633c6b37c484f5f98c3035f49c27395a8ab8", size = 11464613, upload-time = "2026-03-26T18:40:06.301Z" }, + { url = "https://files.pythonhosted.org/packages/f8/22/d7f2fabdba4fae9f3b570e5605d5eb4500dcb7b770d3217dca4428484b17/ruff-0.15.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f29b989a55572fb885b77464cf24af05500806ab4edf9a0fd8977f9759d85b1", size = 11257557, upload-time = "2026-03-26T18:39:57.972Z" }, + { url = "https://files.pythonhosted.org/packages/71/8c/382a9620038cf6906446b23ce8632ab8c0811b8f9d3e764f58bedd0c9a6f/ruff-0.15.8-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:ac51d486bf457cdc985a412fb1801b2dfd1bd8838372fc55de64b1510eff4bec", size = 11169440, upload-time = "2026-03-26T18:39:22.205Z" }, + { url = "https://files.pythonhosted.org/packages/4d/0d/0994c802a7eaaf99380085e4e40c845f8e32a562e20a38ec06174b52ef24/ruff-0.15.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c9861eb959edab053c10ad62c278835ee69ca527b6dcd72b47d5c1e5648964f6", size = 10605963, upload-time = "2026-03-26T18:39:46.682Z" }, + { url = "https://files.pythonhosted.org/packages/19/aa/d624b86f5b0aad7cef6bbf9cd47a6a02dfdc4f72c92a337d724e39c9d14b/ruff-0.15.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8d9a5b8ea13f26ae90838afc33f91b547e61b794865374f114f349e9036835fb", size = 10357484, upload-time = "2026-03-26T18:39:49.176Z" }, + { url = "https://files.pythonhosted.org/packages/35/c3/e0b7835d23001f7d999f3895c6b569927c4d39912286897f625736e1fd04/ruff-0.15.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c2a33a529fb3cbc23a7124b5c6ff121e4d6228029cba374777bd7649cc8598b8", size = 10830426, upload-time = "2026-03-26T18:40:03.702Z" }, + { url = "https://files.pythonhosted.org/packages/f0/51/ab20b322f637b369383adc341d761eaaa0f0203d6b9a7421cd6e783d81b9/ruff-0.15.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:75e5cd06b1cf3f47a3996cfc999226b19aa92e7cce682dcd62f80d7035f98f49", size = 11345125, upload-time = "2026-03-26T18:39:27.799Z" }, + { url = "https://files.pythonhosted.org/packages/37/e6/90b2b33419f59d0f2c4c8a48a4b74b460709a557e8e0064cf33ad894f983/ruff-0.15.8-py3-none-win32.whl", hash = "sha256:bc1f0a51254ba21767bfa9a8b5013ca8149dcf38092e6a9eb704d876de94dc34", size = 10571959, upload-time = "2026-03-26T18:39:36.117Z" }, + { url = "https://files.pythonhosted.org/packages/1f/a2/ef467cb77099062317154c63f234b8a7baf7cb690b99af760c5b68b9ee7f/ruff-0.15.8-py3-none-win_amd64.whl", hash = "sha256:04f79eff02a72db209d47d665ba7ebcad609d8918a134f86cb13dd132159fc89", size = 11743893, upload-time = "2026-03-26T18:39:25.01Z" }, + { url = "https://files.pythonhosted.org/packages/15/e2/77be4fff062fa78d9b2a4dea85d14785dac5f1d0c1fb58ed52331f0ebe28/ruff-0.15.8-py3-none-win_arm64.whl", hash = "sha256:cf891fa8e3bb430c0e7fac93851a5978fc99c8fa2c053b57b118972866f8e5f2", size = 11048175, upload-time = "2026-03-26T18:40:01.06Z" }, ] [[package]] From 428f82c93616b52aee2fcee03484a855135c07e5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Apr 2026 14:27:53 +0000 Subject: [PATCH 43/69] =?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 c072002af4..dbc8a35ddb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* ⬆ Bump ruff from 0.15.0 to 0.15.8. PR [#15277](https://github.com/fastapi/fastapi/pull/15277) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI GitHub topic repositories. PR [#15274](https://github.com/fastapi/fastapi/pull/15274) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump fastmcp from 2.14.5 to 3.2.0. PR [#15267](https://github.com/fastapi/fastapi/pull/15267) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Contributors and Translators. PR [#15270](https://github.com/fastapi/fastapi/pull/15270) by [@tiangolo](https://github.com/tiangolo). From 6c8112555bd86f21cfee8500140dca094ad26e20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:29:59 +0200 Subject: [PATCH 44/69] =?UTF-8?q?=E2=AC=86=20Bump=20orjson=20from=203.11.7?= =?UTF-8?q?=20to=203.11.8=20(#15276)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 154 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/uv.lock b/uv.lock index 67dc875858..9189904a4e 100644 --- a/uv.lock +++ b/uv.lock @@ -3332,83 +3332,83 @@ wheels = [ [[package]] name = "orjson" -version = "3.11.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/53/45/b268004f745ede84e5798b48ee12b05129d19235d0e15267aa57dcdb400b/orjson-3.11.7.tar.gz", hash = "sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49", size = 6144992, upload-time = "2026-02-02T15:38:49.29Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/de/1a/a373746fa6d0e116dd9e54371a7b54622c44d12296d5d0f3ad5e3ff33490/orjson-3.11.7-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a02c833f38f36546ba65a452127633afce4cf0dd7296b753d3bb54e55e5c0174", size = 229140, upload-time = "2026-02-02T15:37:06.082Z" }, - { url = "https://files.pythonhosted.org/packages/52/a2/fa129e749d500f9b183e8a3446a193818a25f60261e9ce143ad61e975208/orjson-3.11.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b63c6e6738d7c3470ad01601e23376aa511e50e1f3931395b9f9c722406d1a67", size = 128670, upload-time = "2026-02-02T15:37:08.002Z" }, - { url = "https://files.pythonhosted.org/packages/08/93/1e82011cd1e0bd051ef9d35bed1aa7fb4ea1f0a055dc2c841b46b43a9ebd/orjson-3.11.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:043d3006b7d32c7e233b8cfb1f01c651013ea079e08dcef7189a29abd8befe11", size = 123832, upload-time = "2026-02-02T15:37:09.191Z" }, - { url = "https://files.pythonhosted.org/packages/fe/d8/a26b431ef962c7d55736674dddade876822f3e33223c1f47a36879350d04/orjson-3.11.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57036b27ac8a25d81112eb0cc9835cd4833c5b16e1467816adc0015f59e870dc", size = 129171, upload-time = "2026-02-02T15:37:11.112Z" }, - { url = "https://files.pythonhosted.org/packages/a7/19/f47819b84a580f490da260c3ee9ade214cf4cf78ac9ce8c1c758f80fdfc9/orjson-3.11.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:733ae23ada68b804b222c44affed76b39e30806d38660bf1eb200520d259cc16", size = 141967, upload-time = "2026-02-02T15:37:12.282Z" }, - { url = "https://files.pythonhosted.org/packages/5b/cd/37ece39a0777ba077fdcdbe4cccae3be8ed00290c14bf8afdc548befc260/orjson-3.11.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5fdfad2093bdd08245f2e204d977facd5f871c88c4a71230d5bcbd0e43bf6222", size = 130991, upload-time = "2026-02-02T15:37:13.465Z" }, - { url = "https://files.pythonhosted.org/packages/8f/ed/f2b5d66aa9b6b5c02ff5f120efc7b38c7c4962b21e6be0f00fd99a5c348e/orjson-3.11.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cededd6738e1c153530793998e31c05086582b08315db48ab66649768f326baa", size = 133674, upload-time = "2026-02-02T15:37:14.694Z" }, - { url = "https://files.pythonhosted.org/packages/c4/6e/baa83e68d1aa09fa8c3e5b2c087d01d0a0bd45256de719ed7bc22c07052d/orjson-3.11.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:14f440c7268c8f8633d1b3d443a434bd70cb15686117ea6beff8fdc8f5917a1e", size = 138722, upload-time = "2026-02-02T15:37:16.501Z" }, - { url = "https://files.pythonhosted.org/packages/0c/47/7f8ef4963b772cd56999b535e553f7eb5cd27e9dd6c049baee6f18bfa05d/orjson-3.11.7-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:3a2479753bbb95b0ebcf7969f562cdb9668e6d12416a35b0dda79febf89cdea2", size = 409056, upload-time = "2026-02-02T15:37:17.895Z" }, - { url = "https://files.pythonhosted.org/packages/38/eb/2df104dd2244b3618f25325a656f85cc3277f74bbd91224752410a78f3c7/orjson-3.11.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:71924496986275a737f38e3f22b4e0878882b3f7a310d2ff4dc96e812789120c", size = 144196, upload-time = "2026-02-02T15:37:19.349Z" }, - { url = "https://files.pythonhosted.org/packages/b6/2a/ee41de0aa3a6686598661eae2b4ebdff1340c65bfb17fcff8b87138aab21/orjson-3.11.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b4a9eefdc70bf8bf9857f0290f973dec534ac84c35cd6a7f4083be43e7170a8f", size = 134979, upload-time = "2026-02-02T15:37:20.906Z" }, - { url = "https://files.pythonhosted.org/packages/4c/fa/92fc5d3d402b87a8b28277a9ed35386218a6a5287c7fe5ee9b9f02c53fb2/orjson-3.11.7-cp310-cp310-win32.whl", hash = "sha256:ae9e0b37a834cef7ce8f99de6498f8fad4a2c0bf6bfc3d02abd8ed56aa15b2de", size = 127968, upload-time = "2026-02-02T15:37:23.178Z" }, - { url = "https://files.pythonhosted.org/packages/07/29/a576bf36d73d60df06904d3844a9df08e25d59eba64363aaf8ec2f9bff41/orjson-3.11.7-cp310-cp310-win_amd64.whl", hash = "sha256:d772afdb22555f0c58cfc741bdae44180122b3616faa1ecadb595cd526e4c993", size = 125128, upload-time = "2026-02-02T15:37:24.329Z" }, - { url = "https://files.pythonhosted.org/packages/37/02/da6cb01fc6087048d7f61522c327edf4250f1683a58a839fdcc435746dd5/orjson-3.11.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9487abc2c2086e7c8eb9a211d2ce8855bae0e92586279d0d27b341d5ad76c85c", size = 228664, upload-time = "2026-02-02T15:37:25.542Z" }, - { url = "https://files.pythonhosted.org/packages/c1/c2/5885e7a5881dba9a9af51bc564e8967225a642b3e03d089289a35054e749/orjson-3.11.7-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:79cacb0b52f6004caf92405a7e1f11e6e2de8bdf9019e4f76b44ba045125cd6b", size = 125344, upload-time = "2026-02-02T15:37:26.92Z" }, - { url = "https://files.pythonhosted.org/packages/a4/1d/4e7688de0a92d1caf600dfd5fb70b4c5bfff51dfa61ac555072ef2d0d32a/orjson-3.11.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2e85fe4698b6a56d5e2ebf7ae87544d668eb6bde1ad1226c13f44663f20ec9e", size = 128404, upload-time = "2026-02-02T15:37:28.108Z" }, - { url = "https://files.pythonhosted.org/packages/2f/b2/ec04b74ae03a125db7bd69cffd014b227b7f341e3261bf75b5eb88a1aa92/orjson-3.11.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b8d14b71c0b12963fe8a62aac87119f1afdf4cb88a400f61ca5ae581449efcb5", size = 123677, upload-time = "2026-02-02T15:37:30.287Z" }, - { url = "https://files.pythonhosted.org/packages/4c/69/f95bdf960605f08f827f6e3291fe243d8aa9c5c9ff017a8d7232209184c3/orjson-3.11.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91c81ef070c8f3220054115e1ef468b1c9ce8497b4e526cb9f68ab4dc0a7ac62", size = 128950, upload-time = "2026-02-02T15:37:31.595Z" }, - { url = "https://files.pythonhosted.org/packages/a4/1b/de59c57bae1d148ef298852abd31909ac3089cff370dfd4cd84cc99cbc42/orjson-3.11.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:411ebaf34d735e25e358a6d9e7978954a9c9d58cfb47bc6683cdc3964cd2f910", size = 141756, upload-time = "2026-02-02T15:37:32.985Z" }, - { url = "https://files.pythonhosted.org/packages/ee/9e/9decc59f4499f695f65c650f6cfa6cd4c37a3fbe8fa235a0a3614cb54386/orjson-3.11.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a16bcd08ab0bcdfc7e8801d9c4a9cc17e58418e4d48ddc6ded4e9e4b1a94062b", size = 130812, upload-time = "2026-02-02T15:37:34.204Z" }, - { url = "https://files.pythonhosted.org/packages/28/e6/59f932bcabd1eac44e334fe8e3281a92eacfcb450586e1f4bde0423728d8/orjson-3.11.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c0b51672e466fd7e56230ffbae7f1639e18d0ce023351fb75da21b71bc2c960", size = 133444, upload-time = "2026-02-02T15:37:35.446Z" }, - { url = "https://files.pythonhosted.org/packages/f1/36/b0f05c0eaa7ca30bc965e37e6a2956b0d67adb87a9872942d3568da846ae/orjson-3.11.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:136dcd6a2e796dfd9ffca9fc027d778567b0b7c9968d092842d3c323cef88aa8", size = 138609, upload-time = "2026-02-02T15:37:36.657Z" }, - { url = "https://files.pythonhosted.org/packages/b8/03/58ec7d302b8d86944c60c7b4b82975d5161fcce4c9bc8c6cb1d6741b6115/orjson-3.11.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:7ba61079379b0ae29e117db13bda5f28d939766e410d321ec1624afc6a0b0504", size = 408918, upload-time = "2026-02-02T15:37:38.076Z" }, - { url = "https://files.pythonhosted.org/packages/06/3a/868d65ef9a8b99be723bd510de491349618abd9f62c826cf206d962db295/orjson-3.11.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0527a4510c300e3b406591b0ba69b5dc50031895b0a93743526a3fc45f59d26e", size = 143998, upload-time = "2026-02-02T15:37:39.706Z" }, - { url = "https://files.pythonhosted.org/packages/5b/c7/1e18e1c83afe3349f4f6dc9e14910f0ae5f82eac756d1412ea4018938535/orjson-3.11.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a709e881723c9b18acddcfb8ba357322491ad553e277cf467e1e7e20e2d90561", size = 134802, upload-time = "2026-02-02T15:37:41.002Z" }, - { url = "https://files.pythonhosted.org/packages/d4/0b/ccb7ee1a65b37e8eeb8b267dc953561d72370e85185e459616d4345bab34/orjson-3.11.7-cp311-cp311-win32.whl", hash = "sha256:c43b8b5bab288b6b90dac410cca7e986a4fa747a2e8f94615aea407da706980d", size = 127828, upload-time = "2026-02-02T15:37:42.241Z" }, - { url = "https://files.pythonhosted.org/packages/af/9e/55c776dffda3f381e0f07d010a4f5f3902bf48eaba1bb7684d301acd4924/orjson-3.11.7-cp311-cp311-win_amd64.whl", hash = "sha256:6543001328aa857187f905308a028935864aefe9968af3848401b6fe80dbb471", size = 124941, upload-time = "2026-02-02T15:37:43.444Z" }, - { url = "https://files.pythonhosted.org/packages/aa/8e/424a620fa7d263b880162505fb107ef5e0afaa765b5b06a88312ac291560/orjson-3.11.7-cp311-cp311-win_arm64.whl", hash = "sha256:1ee5cc7160a821dfe14f130bc8e63e7611051f964b463d9e2a3a573204446a4d", size = 126245, upload-time = "2026-02-02T15:37:45.18Z" }, - { url = "https://files.pythonhosted.org/packages/80/bf/76f4f1665f6983385938f0e2a5d7efa12a58171b8456c252f3bae8a4cf75/orjson-3.11.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bd03ea7606833655048dab1a00734a2875e3e86c276e1d772b2a02556f0d895f", size = 228545, upload-time = "2026-02-02T15:37:46.376Z" }, - { url = "https://files.pythonhosted.org/packages/79/53/6c72c002cb13b5a978a068add59b25a8bdf2800ac1c9c8ecdb26d6d97064/orjson-3.11.7-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:89e440ebc74ce8ab5c7bc4ce6757b4a6b1041becb127df818f6997b5c71aa60b", size = 125224, upload-time = "2026-02-02T15:37:47.697Z" }, - { url = "https://files.pythonhosted.org/packages/2c/83/10e48852865e5dd151bdfe652c06f7da484578ed02c5fca938e3632cb0b8/orjson-3.11.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ede977b5fe5ac91b1dffc0a517ca4542d2ec8a6a4ff7b2652d94f640796342a", size = 128154, upload-time = "2026-02-02T15:37:48.954Z" }, - { url = "https://files.pythonhosted.org/packages/6e/52/a66e22a2b9abaa374b4a081d410edab6d1e30024707b87eab7c734afe28d/orjson-3.11.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b7b1dae39230a393df353827c855a5f176271c23434cfd2db74e0e424e693e10", size = 123548, upload-time = "2026-02-02T15:37:50.187Z" }, - { url = "https://files.pythonhosted.org/packages/de/38/605d371417021359f4910c496f764c48ceb8997605f8c25bf1dfe58c0ebe/orjson-3.11.7-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed46f17096e28fb28d2975834836a639af7278aa87c84f68ab08fbe5b8bd75fa", size = 129000, upload-time = "2026-02-02T15:37:51.426Z" }, - { url = "https://files.pythonhosted.org/packages/44/98/af32e842b0ffd2335c89714d48ca4e3917b42f5d6ee5537832e069a4b3ac/orjson-3.11.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3726be79e36e526e3d9c1aceaadbfb4a04ee80a72ab47b3f3c17fefb9812e7b8", size = 141686, upload-time = "2026-02-02T15:37:52.607Z" }, - { url = "https://files.pythonhosted.org/packages/96/0b/fc793858dfa54be6feee940c1463370ece34b3c39c1ca0aa3845f5ba9892/orjson-3.11.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0724e265bc548af1dedebd9cb3d24b4e1c1e685a343be43e87ba922a5c5fff2f", size = 130812, upload-time = "2026-02-02T15:37:53.944Z" }, - { url = "https://files.pythonhosted.org/packages/dc/91/98a52415059db3f374757d0b7f0f16e3b5cd5976c90d1c2b56acaea039e6/orjson-3.11.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7745312efa9e11c17fbd3cb3097262d079da26930ae9ae7ba28fb738367cbad", size = 133440, upload-time = "2026-02-02T15:37:55.615Z" }, - { url = "https://files.pythonhosted.org/packages/dc/b6/cb540117bda61791f46381f8c26c8f93e802892830a6055748d3bb1925ab/orjson-3.11.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f904c24bdeabd4298f7a977ef14ca2a022ca921ed670b92ecd16ab6f3d01f867", size = 138386, upload-time = "2026-02-02T15:37:56.814Z" }, - { url = "https://files.pythonhosted.org/packages/63/1a/50a3201c334a7f17c231eee5f841342190723794e3b06293f26e7cf87d31/orjson-3.11.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b9fc4d0f81f394689e0814617aadc4f2ea0e8025f38c226cbf22d3b5ddbf025d", size = 408853, upload-time = "2026-02-02T15:37:58.291Z" }, - { url = "https://files.pythonhosted.org/packages/87/cd/8de1c67d0be44fdc22701e5989c0d015a2adf391498ad42c4dc589cd3013/orjson-3.11.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:849e38203e5be40b776ed2718e587faf204d184fc9a008ae441f9442320c0cab", size = 144130, upload-time = "2026-02-02T15:38:00.163Z" }, - { url = "https://files.pythonhosted.org/packages/0f/fe/d605d700c35dd55f51710d159fc54516a280923cd1b7e47508982fbb387d/orjson-3.11.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4682d1db3bcebd2b64757e0ddf9e87ae5f00d29d16c5cdf3a62f561d08cc3dd2", size = 134818, upload-time = "2026-02-02T15:38:01.507Z" }, - { url = "https://files.pythonhosted.org/packages/e4/e4/15ecc67edb3ddb3e2f46ae04475f2d294e8b60c1825fbe28a428b93b3fbd/orjson-3.11.7-cp312-cp312-win32.whl", hash = "sha256:f4f7c956b5215d949a1f65334cf9d7612dde38f20a95f2315deef167def91a6f", size = 127923, upload-time = "2026-02-02T15:38:02.75Z" }, - { url = "https://files.pythonhosted.org/packages/34/70/2e0855361f76198a3965273048c8e50a9695d88cd75811a5b46444895845/orjson-3.11.7-cp312-cp312-win_amd64.whl", hash = "sha256:bf742e149121dc5648ba0a08ea0871e87b660467ef168a3a5e53bc1fbd64bb74", size = 125007, upload-time = "2026-02-02T15:38:04.032Z" }, - { url = "https://files.pythonhosted.org/packages/68/40/c2051bd19fc467610fed469dc29e43ac65891571138f476834ca192bc290/orjson-3.11.7-cp312-cp312-win_arm64.whl", hash = "sha256:26c3b9132f783b7d7903bf1efb095fed8d4a3a85ec0d334ee8beff3d7a4749d5", size = 126089, upload-time = "2026-02-02T15:38:05.297Z" }, - { url = "https://files.pythonhosted.org/packages/89/25/6e0e52cac5aab51d7b6dcd257e855e1dec1c2060f6b28566c509b4665f62/orjson-3.11.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1d98b30cc1313d52d4af17d9c3d307b08389752ec5f2e5febdfada70b0f8c733", size = 228390, upload-time = "2026-02-02T15:38:06.8Z" }, - { url = "https://files.pythonhosted.org/packages/a5/29/a77f48d2fc8a05bbc529e5ff481fb43d914f9e383ea2469d4f3d51df3d00/orjson-3.11.7-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:d897e81f8d0cbd2abb82226d1860ad2e1ab3ff16d7b08c96ca00df9d45409ef4", size = 125189, upload-time = "2026-02-02T15:38:08.181Z" }, - { url = "https://files.pythonhosted.org/packages/89/25/0a16e0729a0e6a1504f9d1a13cdd365f030068aab64cec6958396b9969d7/orjson-3.11.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:814be4b49b228cfc0b3c565acf642dd7d13538f966e3ccde61f4f55be3e20785", size = 128106, upload-time = "2026-02-02T15:38:09.41Z" }, - { url = "https://files.pythonhosted.org/packages/66/da/a2e505469d60666a05ab373f1a6322eb671cb2ba3a0ccfc7d4bc97196787/orjson-3.11.7-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d06e5c5fed5caedd2e540d62e5b1c25e8c82431b9e577c33537e5fa4aa909539", size = 123363, upload-time = "2026-02-02T15:38:10.73Z" }, - { url = "https://files.pythonhosted.org/packages/23/bf/ed73f88396ea35c71b38961734ea4a4746f7ca0768bf28fd551d37e48dd0/orjson-3.11.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31c80ce534ac4ea3739c5ee751270646cbc46e45aea7576a38ffec040b4029a1", size = 129007, upload-time = "2026-02-02T15:38:12.138Z" }, - { url = "https://files.pythonhosted.org/packages/73/3c/b05d80716f0225fc9008fbf8ab22841dcc268a626aa550561743714ce3bf/orjson-3.11.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f50979824bde13d32b4320eedd513431c921102796d86be3eee0b58e58a3ecd1", size = 141667, upload-time = "2026-02-02T15:38:13.398Z" }, - { url = "https://files.pythonhosted.org/packages/61/e8/0be9b0addd9bf86abfc938e97441dcd0375d494594b1c8ad10fe57479617/orjson-3.11.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e54f3808e2b6b945078c41aa8d9b5834b28c50843846e97807e5adb75fa9705", size = 130832, upload-time = "2026-02-02T15:38:14.698Z" }, - { url = "https://files.pythonhosted.org/packages/c9/ec/c68e3b9021a31d9ec15a94931db1410136af862955854ed5dd7e7e4f5bff/orjson-3.11.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12b80df61aab7b98b490fe9e4879925ba666fccdfcd175252ce4d9035865ace", size = 133373, upload-time = "2026-02-02T15:38:16.109Z" }, - { url = "https://files.pythonhosted.org/packages/d2/45/f3466739aaafa570cc8e77c6dbb853c48bf56e3b43738020e2661e08b0ac/orjson-3.11.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:996b65230271f1a97026fd0e6a753f51fbc0c335d2ad0c6201f711b0da32693b", size = 138307, upload-time = "2026-02-02T15:38:17.453Z" }, - { url = "https://files.pythonhosted.org/packages/e1/84/9f7f02288da1ffb31405c1be07657afd1eecbcb4b64ee2817b6fe0f785fa/orjson-3.11.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ab49d4b2a6a1d415ddb9f37a21e02e0d5dbfe10b7870b21bf779fc21e9156157", size = 408695, upload-time = "2026-02-02T15:38:18.831Z" }, - { url = "https://files.pythonhosted.org/packages/18/07/9dd2f0c0104f1a0295ffbe912bc8d63307a539b900dd9e2c48ef7810d971/orjson-3.11.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:390a1dce0c055ddf8adb6aa94a73b45a4a7d7177b5c584b8d1c1947f2ba60fb3", size = 144099, upload-time = "2026-02-02T15:38:20.28Z" }, - { url = "https://files.pythonhosted.org/packages/a5/66/857a8e4a3292e1f7b1b202883bcdeb43a91566cf59a93f97c53b44bd6801/orjson-3.11.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1eb80451a9c351a71dfaf5b7ccc13ad065405217726b59fdbeadbcc544f9d223", size = 134806, upload-time = "2026-02-02T15:38:22.186Z" }, - { url = "https://files.pythonhosted.org/packages/0a/5b/6ebcf3defc1aab3a338ca777214966851e92efb1f30dc7fc8285216e6d1b/orjson-3.11.7-cp313-cp313-win32.whl", hash = "sha256:7477aa6a6ec6139c5cb1cc7b214643592169a5494d200397c7fc95d740d5fcf3", size = 127914, upload-time = "2026-02-02T15:38:23.511Z" }, - { url = "https://files.pythonhosted.org/packages/00/04/c6f72daca5092e3117840a1b1e88dfc809cc1470cf0734890d0366b684a1/orjson-3.11.7-cp313-cp313-win_amd64.whl", hash = "sha256:b9f95dcdea9d4f805daa9ddf02617a89e484c6985fa03055459f90e87d7a0757", size = 124986, upload-time = "2026-02-02T15:38:24.836Z" }, - { url = "https://files.pythonhosted.org/packages/03/ba/077a0f6f1085d6b806937246860fafbd5b17f3919c70ee3f3d8d9c713f38/orjson-3.11.7-cp313-cp313-win_arm64.whl", hash = "sha256:800988273a014a0541483dc81021247d7eacb0c845a9d1a34a422bc718f41539", size = 126045, upload-time = "2026-02-02T15:38:26.216Z" }, - { url = "https://files.pythonhosted.org/packages/e9/1e/745565dca749813db9a093c5ebc4bac1a9475c64d54b95654336ac3ed961/orjson-3.11.7-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:de0a37f21d0d364954ad5de1970491d7fbd0fb1ef7417d4d56a36dc01ba0c0a0", size = 228391, upload-time = "2026-02-02T15:38:27.757Z" }, - { url = "https://files.pythonhosted.org/packages/46/19/e40f6225da4d3aa0c8dc6e5219c5e87c2063a560fe0d72a88deb59776794/orjson-3.11.7-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c2428d358d85e8da9d37cba18b8c4047c55222007a84f97156a5b22028dfbfc0", size = 125188, upload-time = "2026-02-02T15:38:29.241Z" }, - { url = "https://files.pythonhosted.org/packages/9d/7e/c4de2babef2c0817fd1f048fd176aa48c37bec8aef53d2fa932983032cce/orjson-3.11.7-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c4bc6c6ac52cdaa267552544c73e486fecbd710b7ac09bc024d5a78555a22f6", size = 128097, upload-time = "2026-02-02T15:38:30.618Z" }, - { url = "https://files.pythonhosted.org/packages/eb/74/233d360632bafd2197f217eee7fb9c9d0229eac0c18128aee5b35b0014fe/orjson-3.11.7-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd0d68edd7dfca1b2eca9361a44ac9f24b078de3481003159929a0573f21a6bf", size = 123364, upload-time = "2026-02-02T15:38:32.363Z" }, - { url = "https://files.pythonhosted.org/packages/79/51/af79504981dd31efe20a9e360eb49c15f06df2b40e7f25a0a52d9ae888e8/orjson-3.11.7-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:623ad1b9548ef63886319c16fa317848e465a21513b31a6ad7b57443c3e0dcf5", size = 129076, upload-time = "2026-02-02T15:38:33.68Z" }, - { url = "https://files.pythonhosted.org/packages/67/e2/da898eb68b72304f8de05ca6715870d09d603ee98d30a27e8a9629abc64b/orjson-3.11.7-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6e776b998ac37c0396093d10290e60283f59cfe0fc3fccbd0ccc4bd04dd19892", size = 141705, upload-time = "2026-02-02T15:38:34.989Z" }, - { url = "https://files.pythonhosted.org/packages/c5/89/15364d92acb3d903b029e28d834edb8780c2b97404cbf7929aa6b9abdb24/orjson-3.11.7-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:652c6c3af76716f4a9c290371ba2e390ede06f6603edb277b481daf37f6f464e", size = 130855, upload-time = "2026-02-02T15:38:36.379Z" }, - { url = "https://files.pythonhosted.org/packages/c2/8b/ecdad52d0b38d4b8f514be603e69ccd5eacf4e7241f972e37e79792212ec/orjson-3.11.7-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a56df3239294ea5964adf074c54bcc4f0ccd21636049a2cf3ca9cf03b5d03cf1", size = 133386, upload-time = "2026-02-02T15:38:37.704Z" }, - { url = "https://files.pythonhosted.org/packages/b9/0e/45e1dcf10e17d0924b7c9162f87ec7b4ca79e28a0548acf6a71788d3e108/orjson-3.11.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bda117c4148e81f746655d5a3239ae9bd00cb7bc3ca178b5fc5a5997e9744183", size = 138295, upload-time = "2026-02-02T15:38:39.096Z" }, - { url = "https://files.pythonhosted.org/packages/63/d7/4d2e8b03561257af0450f2845b91fbd111d7e526ccdf737267108075e0ba/orjson-3.11.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:23d6c20517a97a9daf1d48b580fcdc6f0516c6f4b5038823426033690b4d2650", size = 408720, upload-time = "2026-02-02T15:38:40.634Z" }, - { url = "https://files.pythonhosted.org/packages/78/cf/d45343518282108b29c12a65892445fc51f9319dc3c552ceb51bb5905ed2/orjson-3.11.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:8ff206156006da5b847c9304b6308a01e8cdbc8cce824e2779a5ba71c3def141", size = 144152, upload-time = "2026-02-02T15:38:42.262Z" }, - { url = "https://files.pythonhosted.org/packages/a9/3a/d6001f51a7275aacd342e77b735c71fa04125a3f93c36fee4526bc8c654e/orjson-3.11.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:962d046ee1765f74a1da723f4b33e3b228fe3a48bd307acce5021dfefe0e29b2", size = 134814, upload-time = "2026-02-02T15:38:43.627Z" }, - { url = "https://files.pythonhosted.org/packages/1d/d3/f19b47ce16820cc2c480f7f1723e17f6d411b3a295c60c8ad3aa9ff1c96a/orjson-3.11.7-cp314-cp314-win32.whl", hash = "sha256:89e13dd3f89f1c38a9c9eba5fbf7cdc2d1feca82f5f290864b4b7a6aac704576", size = 127997, upload-time = "2026-02-02T15:38:45.06Z" }, - { url = "https://files.pythonhosted.org/packages/12/df/172771902943af54bf661a8d102bdf2e7f932127968080632bda6054b62c/orjson-3.11.7-cp314-cp314-win_amd64.whl", hash = "sha256:845c3e0d8ded9c9271cd79596b9b552448b885b97110f628fb687aee2eed11c1", size = 124985, upload-time = "2026-02-02T15:38:46.388Z" }, - { url = "https://files.pythonhosted.org/packages/6f/1c/f2a8d8a1b17514660a614ce5f7aac74b934e69f5abc2700cc7ced882a009/orjson-3.11.7-cp314-cp314-win_arm64.whl", hash = "sha256:4a2e9c5be347b937a2e0203866f12bba36082e89b402ddb9e927d5822e43088d", size = 126038, upload-time = "2026-02-02T15:38:47.703Z" }, +version = "3.11.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9d/1b/2024d06792d0779f9dbc51531b61c24f76c75b9f4ce05e6f3377a1814cea/orjson-3.11.8.tar.gz", hash = "sha256:96163d9cdc5a202703e9ad1b9ae757d5f0ca62f4fa0cc93d1f27b0e180cc404e", size = 5603832, upload-time = "2026-03-31T16:16:27.878Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/90/5d81f61fe3e4270da80c71442864c091cee3003cc8984c75f413fe742a07/orjson-3.11.8-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e6693ff90018600c72fd18d3d22fa438be26076cd3c823da5f63f7bab28c11cb", size = 229663, upload-time = "2026-03-31T16:14:30.708Z" }, + { url = "https://files.pythonhosted.org/packages/6c/ef/85e06b0eb11de6fb424120fd5788a07035bd4c5e6bb7841ae9972a0526d1/orjson-3.11.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93de06bc920854552493c81f1f729fab7213b7db4b8195355db5fda02c7d1363", size = 132321, upload-time = "2026-03-31T16:14:32.317Z" }, + { url = "https://files.pythonhosted.org/packages/86/71/089338ee51b3132f050db0864a7df9bdd5e94c2a03820ab8a91e8f655618/orjson-3.11.8-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fe0b8c83e0f36247fc9431ce5425a5d95f9b3a689133d494831bdbd6f0bceb13", size = 130658, upload-time = "2026-03-31T16:14:33.935Z" }, + { url = "https://files.pythonhosted.org/packages/10/0d/f39d8802345d0ad65f7fd4374b29b9b59f98656dc30f21ca5c773265b2f0/orjson-3.11.8-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97d823831105c01f6c8029faf297633dbeb30271892bd430e9c24ceae3734744", size = 135708, upload-time = "2026-03-31T16:14:35.224Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b5/40aae576b3473511696dcffea84fde638b2b64774eb4dcb8b2c262729f8a/orjson-3.11.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c60c0423f15abb6cf78f56dff00168a1b582f7a1c23f114036e2bfc697814d5f", size = 147047, upload-time = "2026-03-31T16:14:36.489Z" }, + { url = "https://files.pythonhosted.org/packages/7b/f0/778a84458d1fdaa634b2e572e51ce0b354232f580b2327e1f00a8d88c38c/orjson-3.11.8-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:01928d0476b216ad2201823b0a74000440360cef4fed1912d297b8d84718f277", size = 133072, upload-time = "2026-03-31T16:14:37.715Z" }, + { url = "https://files.pythonhosted.org/packages/bf/d3/1bbf2fc3ffcc4b829ade554b574af68cec898c9b5ad6420a923c75a073d3/orjson-3.11.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a4a639049c44d36a6d1ae0f4a94b271605c745aee5647fa8ffaabcdc01b69a6", size = 133867, upload-time = "2026-03-31T16:14:39.356Z" }, + { url = "https://files.pythonhosted.org/packages/08/94/6413da22edc99a69a8d0c2e83bf42973b8aa94d83ef52a6d39ac85da00bc/orjson-3.11.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3222adff1e1ff0dce93c16146b93063a7793de6c43d52309ae321234cdaf0f4d", size = 142268, upload-time = "2026-03-31T16:14:40.972Z" }, + { url = "https://files.pythonhosted.org/packages/4a/5f/aa5dbaa6136d7ba55f5461ac2e885efc6e6349424a428927fd46d68f4396/orjson-3.11.8-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:3223665349bbfb68da234acd9846955b1a0808cbe5520ff634bf253a4407009b", size = 424008, upload-time = "2026-03-31T16:14:42.637Z" }, + { url = "https://files.pythonhosted.org/packages/fa/aa/2c1962d108c7fe5e27aa03a354b378caf56d8eafdef15fd83dec081ce45a/orjson-3.11.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:61c9d357a59465736022d5d9ba06687afb7611dfb581a9d2129b77a6fcf78e59", size = 147942, upload-time = "2026-03-31T16:14:44.256Z" }, + { url = "https://files.pythonhosted.org/packages/47/d1/65f404f4c47eb1b0b4476f03ec838cac0c4aa933920ff81e5dda4dee14e7/orjson-3.11.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:58fb9b17b4472c7b1dcf1a54583629e62e23779b2331052f09a9249edf81675b", size = 136640, upload-time = "2026-03-31T16:14:45.884Z" }, + { url = "https://files.pythonhosted.org/packages/90/5f/7b784aea98bdb125a2f2da7c27d6c2d2f6d943d96ef0278bae596d563f85/orjson-3.11.8-cp310-cp310-win32.whl", hash = "sha256:b43dc2a391981d36c42fa57747a49dae793ef1d2e43898b197925b5534abd10a", size = 132066, upload-time = "2026-03-31T16:14:47.397Z" }, + { url = "https://files.pythonhosted.org/packages/92/ec/2e284af8d6c9478df5ef938917743f61d68f4c70d17f1b6e82f7e3b8dba1/orjson-3.11.8-cp310-cp310-win_amd64.whl", hash = "sha256:c98121237fea2f679480765abd566f7713185897f35c9e6c2add7e3a9900eb61", size = 127609, upload-time = "2026-03-31T16:14:48.78Z" }, + { url = "https://files.pythonhosted.org/packages/67/41/5aa7fa3b0f4dc6b47dcafc3cea909299c37e40e9972feabc8b6a74e2730d/orjson-3.11.8-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:003646067cc48b7fcab2ae0c562491c9b5d2cbd43f1e5f16d98fd118c5522d34", size = 229229, upload-time = "2026-03-31T16:14:50.424Z" }, + { url = "https://files.pythonhosted.org/packages/0a/d7/57e7f2458e0a2c41694f39fc830030a13053a84f837a5b73423dca1f0938/orjson-3.11.8-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:ed193ce51d77a3830cad399a529cd4ef029968761f43ddc549e1bc62b40d88f8", size = 128871, upload-time = "2026-03-31T16:14:51.888Z" }, + { url = "https://files.pythonhosted.org/packages/53/4a/e0fdb9430983e6c46e0299559275025075568aad5d21dd606faee3703924/orjson-3.11.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30491bc4f862aa15744b9738517454f1e46e56c972a2be87d70d727d5b2a8f8", size = 132104, upload-time = "2026-03-31T16:14:53.142Z" }, + { url = "https://files.pythonhosted.org/packages/08/4a/2025a60ff3f5c8522060cda46612d9b1efa653de66ed2908591d8d82f22d/orjson-3.11.8-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eda5b8b6be91d3f26efb7dc6e5e68ee805bc5617f65a328587b35255f138bf4", size = 130483, upload-time = "2026-03-31T16:14:54.605Z" }, + { url = "https://files.pythonhosted.org/packages/2d/3c/b9cde05bdc7b2385c66014e0620627da638d3d04e4954416ab48c31196c5/orjson-3.11.8-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee8db7bfb6fe03581bbab54d7c4124a6dd6a7f4273a38f7267197890f094675f", size = 135481, upload-time = "2026-03-31T16:14:55.901Z" }, + { url = "https://files.pythonhosted.org/packages/ff/f2/a8238e7734de7cb589fed319857a8025d509c89dc52fdcc88f39c6d03d5a/orjson-3.11.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d8b5231de76c528a46b57010bbd83fb51e056aa0220a372fd5065e978406f1c", size = 146819, upload-time = "2026-03-31T16:14:57.548Z" }, + { url = "https://files.pythonhosted.org/packages/db/10/dbf1e2a3cafea673b1b4350e371877b759060d6018a998643b7040e5de48/orjson-3.11.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:58a4a208a6fbfdb7a7327b8f201c6014f189f721fd55d047cafc4157af1bc62a", size = 132846, upload-time = "2026-03-31T16:14:58.91Z" }, + { url = "https://files.pythonhosted.org/packages/f8/fc/55e667ec9c85694038fcff00573d221b085d50777368ee3d77f38668bf3c/orjson-3.11.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f8952d6d2505c003e8f0224ff7858d341fa4e33fef82b91c4ff0ef070f2393c", size = 133580, upload-time = "2026-03-31T16:15:00.519Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a6/c08c589a9aad0cb46c4831d17de212a2b6901f9d976814321ff8e69e8785/orjson-3.11.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0022bb50f90da04b009ce32c512dc1885910daa7cb10b7b0cba4505b16db82a8", size = 142042, upload-time = "2026-03-31T16:15:01.906Z" }, + { url = "https://files.pythonhosted.org/packages/5c/cc/2f78ea241d52b717d2efc38878615fe80425bf2beb6e68c984dde257a766/orjson-3.11.8-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ff51f9d657d1afb6f410cb435792ce4e1fe427aab23d2fcd727a2876e21d4cb6", size = 423845, upload-time = "2026-03-31T16:15:03.703Z" }, + { url = "https://files.pythonhosted.org/packages/70/07/c17dcf05dd8045457538428a983bf1f1127928df5bf328cb24d2b7cddacb/orjson-3.11.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6dbe9a97bdb4d8d9d5367b52a7c32549bba70b2739c58ef74a6964a6d05ae054", size = 147729, upload-time = "2026-03-31T16:15:05.203Z" }, + { url = "https://files.pythonhosted.org/packages/90/6c/0fb6e8a24e682e0958d71711ae6f39110e4b9cd8cab1357e2a89cb8e1951/orjson-3.11.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5c370674ebabe16c6ccac33ff80c62bf8a6e59439f5e9d40c1f5ab8fd2215b7", size = 136425, upload-time = "2026-03-31T16:15:07.052Z" }, + { url = "https://files.pythonhosted.org/packages/b2/35/4d3cc3a3d616035beb51b24a09bb872942dc452cf2df0c1d11ab35046d9f/orjson-3.11.8-cp311-cp311-win32.whl", hash = "sha256:0e32f7154299f42ae66f13488963269e5eccb8d588a65bc839ed986919fc9fac", size = 131870, upload-time = "2026-03-31T16:15:08.678Z" }, + { url = "https://files.pythonhosted.org/packages/13/26/9fe70f81d16b702f8c3a775e8731b50ad91d22dacd14c7599b60a0941cd1/orjson-3.11.8-cp311-cp311-win_amd64.whl", hash = "sha256:25e0c672a2e32348d2eb33057b41e754091f2835f87222e4675b796b92264f06", size = 127440, upload-time = "2026-03-31T16:15:09.994Z" }, + { url = "https://files.pythonhosted.org/packages/e8/c6/b038339f4145efd2859c1ca53097a52c0bb9cbdd24f947ebe146da1ad067/orjson-3.11.8-cp311-cp311-win_arm64.whl", hash = "sha256:9185589c1f2a944c17e26c9925dcdbc2df061cc4a145395c57f0c51f9b5dbfcd", size = 127399, upload-time = "2026-03-31T16:15:11.412Z" }, + { url = "https://files.pythonhosted.org/packages/01/f6/8d58b32ab32d9215973a1688aebd098252ee8af1766c0e4e36e7831f0295/orjson-3.11.8-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1cd0b77e77c95758f8e1100139844e99f3ccc87e71e6fc8e1c027e55807c549f", size = 229233, upload-time = "2026-03-31T16:15:12.762Z" }, + { url = "https://files.pythonhosted.org/packages/a9/8b/2ffe35e71f6b92622e8ea4607bf33ecf7dfb51b3619dcfabfd36cbe2d0a5/orjson-3.11.8-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:6a3d159d5ffa0e3961f353c4b036540996bf8b9697ccc38261c0eac1fd3347a6", size = 128772, upload-time = "2026-03-31T16:15:14.237Z" }, + { url = "https://files.pythonhosted.org/packages/27/d2/1f8682ae50d5c6897a563cb96bc106da8c9cb5b7b6e81a52e4cc086679b9/orjson-3.11.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76070a76e9c5ae661e2d9848f216980d8d533e0f8143e6ed462807b242e3c5e8", size = 131946, upload-time = "2026-03-31T16:15:15.607Z" }, + { url = "https://files.pythonhosted.org/packages/52/4b/5500f76f0eece84226e0689cb48dcde081104c2fa6e2483d17ca13685ffb/orjson-3.11.8-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:54153d21520a71a4c82a0dbb4523e468941d549d221dc173de0f019678cf3813", size = 130368, upload-time = "2026-03-31T16:15:17.066Z" }, + { url = "https://files.pythonhosted.org/packages/da/4e/58b927e08fbe9840e6c920d9e299b051ea667463b1f39a56e668669f8508/orjson-3.11.8-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:469ac2125611b7c5741a0b3798cd9e5786cbad6345f9f400c77212be89563bec", size = 135540, upload-time = "2026-03-31T16:15:18.404Z" }, + { url = "https://files.pythonhosted.org/packages/56/7c/ba7cb871cba1bcd5cd02ee34f98d894c6cea96353ad87466e5aef2429c60/orjson-3.11.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14778ffd0f6896aa613951a7fbf4690229aa7a543cb2bfbe9f358e08aafa9546", size = 146877, upload-time = "2026-03-31T16:15:19.833Z" }, + { url = "https://files.pythonhosted.org/packages/0b/5d/eb9c25fc1386696c6a342cd361c306452c75e0b55e86ad602dd4827a7fd7/orjson-3.11.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea56a955056a6d6c550cf18b3348656a9d9a4f02e2d0c02cabf3c73f1055d506", size = 132837, upload-time = "2026-03-31T16:15:21.282Z" }, + { url = "https://files.pythonhosted.org/packages/37/87/5ddeb7fc1fbd9004aeccab08426f34c81a5b4c25c7061281862b015fce2b/orjson-3.11.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53a0f57e59a530d18a142f4d4ba6dfc708dc5fdedce45e98ff06b44930a2a48f", size = 133624, upload-time = "2026-03-31T16:15:22.641Z" }, + { url = "https://files.pythonhosted.org/packages/22/09/90048793db94ee4b2fcec4ac8e5ddb077367637d6650be896b3494b79bb7/orjson-3.11.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b48e274f8824567d74e2158199e269597edf00823a1b12b63d48462bbf5123e", size = 141904, upload-time = "2026-03-31T16:15:24.435Z" }, + { url = "https://files.pythonhosted.org/packages/c0/cf/eb284847487821a5d415e54149a6449ba9bfc5872ce63ab7be41b8ec401c/orjson-3.11.8-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3f262401086a3960586af06c054609365e98407151f5ea24a62893a40d80dbbb", size = 423742, upload-time = "2026-03-31T16:15:26.155Z" }, + { url = "https://files.pythonhosted.org/packages/44/09/e12423d327071c851c13e76936f144a96adacfc037394dec35ac3fc8d1e8/orjson-3.11.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8e8c6218b614badf8e229b697865df4301afa74b791b6c9ade01d19a9953a942", size = 147806, upload-time = "2026-03-31T16:15:27.909Z" }, + { url = "https://files.pythonhosted.org/packages/b3/6d/37c2589ba864e582ffe7611643314785c6afb1f83c701654ef05daa8fcc7/orjson-3.11.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:093d489fa039ddade2db541097dbb484999fcc65fc2b0ff9819141e2ab364f25", size = 136485, upload-time = "2026-03-31T16:15:29.749Z" }, + { url = "https://files.pythonhosted.org/packages/be/c9/135194a02ab76b04ed9a10f68624b7ebd238bbe55548878b11ff15a0f352/orjson-3.11.8-cp312-cp312-win32.whl", hash = "sha256:e0950ed1bcb9893f4293fd5c5a7ee10934fbf82c4101c70be360db23ce24b7d2", size = 131966, upload-time = "2026-03-31T16:15:31.687Z" }, + { url = "https://files.pythonhosted.org/packages/ed/9a/9796f8fbe3cf30ce9cb696748dbb535e5c87be4bf4fe2e9ca498ef1fa8cf/orjson-3.11.8-cp312-cp312-win_amd64.whl", hash = "sha256:3cf17c141617b88ced4536b2135c552490f07799f6ad565948ea07bef0dcb9a6", size = 127441, upload-time = "2026-03-31T16:15:33.333Z" }, + { url = "https://files.pythonhosted.org/packages/cc/47/5aaf54524a7a4a0dd09dd778f3fa65dd2108290615b652e23d944152bc8e/orjson-3.11.8-cp312-cp312-win_arm64.whl", hash = "sha256:48854463b0572cc87dac7d981aa72ed8bf6deedc0511853dc76b8bbd5482d36d", size = 127364, upload-time = "2026-03-31T16:15:34.748Z" }, + { url = "https://files.pythonhosted.org/packages/66/7f/95fba509bb2305fab0073558f1e8c3a2ec4b2afe58ed9fcb7d3b8beafe94/orjson-3.11.8-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:3f23426851d98478c8970da5991f84784a76682213cd50eb73a1da56b95239dc", size = 229180, upload-time = "2026-03-31T16:15:36.426Z" }, + { url = "https://files.pythonhosted.org/packages/f6/9d/b237215c743ca073697d759b5503abd2cb8a0d7b9c9e21f524bcf176ab66/orjson-3.11.8-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:ebaed4cef74a045b83e23537b52ef19a367c7e3f536751e355a2a394f8648559", size = 128754, upload-time = "2026-03-31T16:15:38.049Z" }, + { url = "https://files.pythonhosted.org/packages/42/3d/27d65b6d11e63f133781425f132807aef793ed25075fec686fc8e46dd528/orjson-3.11.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97c8f5d3b62380b70c36ffacb2a356b7c6becec86099b177f73851ba095ef623", size = 131877, upload-time = "2026-03-31T16:15:39.484Z" }, + { url = "https://files.pythonhosted.org/packages/dd/cc/faee30cd8f00421999e40ef0eba7332e3a625ce91a58200a2f52c7fef235/orjson-3.11.8-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:436c4922968a619fb7fef1ccd4b8b3a76c13b67d607073914d675026e911a65c", size = 130361, upload-time = "2026-03-31T16:15:41.274Z" }, + { url = "https://files.pythonhosted.org/packages/5c/bb/a6c55896197f97b6d4b4e7c7fd77e7235517c34f5d6ad5aadd43c54c6d7c/orjson-3.11.8-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ab359aff0436d80bfe8a23b46b5fea69f1e18aaf1760a709b4787f1318b317f", size = 135521, upload-time = "2026-03-31T16:15:42.758Z" }, + { url = "https://files.pythonhosted.org/packages/9c/7c/ca3a3525aa32ff636ebb1778e77e3587b016ab2edb1b618b36ba96f8f2c0/orjson-3.11.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f89b6d0b3a8d81e1929d3ab3d92bbc225688bd80a770c49432543928fe09ac55", size = 146862, upload-time = "2026-03-31T16:15:44.341Z" }, + { url = "https://files.pythonhosted.org/packages/3c/0c/18a9d7f18b5edd37344d1fd5be17e94dc652c67826ab749c6e5948a78112/orjson-3.11.8-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29c009e7a2ca9ad0ed1376ce20dd692146a5d9fe4310848904b6b4fee5c5c137", size = 132847, upload-time = "2026-03-31T16:15:46.368Z" }, + { url = "https://files.pythonhosted.org/packages/23/91/7e722f352ad67ca573cee44de2a58fb810d0f4eb4e33276c6a557979fd8a/orjson-3.11.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:705b895b781b3e395c067129d8551655642dfe9437273211d5404e87ac752b53", size = 133637, upload-time = "2026-03-31T16:15:48.123Z" }, + { url = "https://files.pythonhosted.org/packages/af/04/32845ce13ac5bd1046ddb02ac9432ba856cc35f6d74dde95864fe0ad5523/orjson-3.11.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:88006eda83858a9fdf73985ce3804e885c2befb2f506c9a3723cdeb5a2880e3e", size = 141906, upload-time = "2026-03-31T16:15:49.626Z" }, + { url = "https://files.pythonhosted.org/packages/02/5e/c551387ddf2d7106d9039369862245c85738b828844d13b99ccb8d61fd06/orjson-3.11.8-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:55120759e61309af7fcf9e961c6f6af3dde5921cdb3ee863ef63fd9db126cae6", size = 423722, upload-time = "2026-03-31T16:15:51.176Z" }, + { url = "https://files.pythonhosted.org/packages/00/a3/ecfe62434096f8a794d4976728cb59bcfc4a643977f21c2040545d37eb4c/orjson-3.11.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:98bdc6cb889d19bed01de46e67574a2eab61f5cc6b768ed50e8ac68e9d6ffab6", size = 147801, upload-time = "2026-03-31T16:15:52.939Z" }, + { url = "https://files.pythonhosted.org/packages/18/6d/0dce10b9f6643fdc59d99333871a38fa5a769d8e2fc34a18e5d2bfdee900/orjson-3.11.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:708c95f925a43ab9f34625e45dcdadf09ec8a6e7b664a938f2f8d5650f6c090b", size = 136460, upload-time = "2026-03-31T16:15:54.431Z" }, + { url = "https://files.pythonhosted.org/packages/01/d6/6dde4f31842d87099238f1f07b459d24edc1a774d20687187443ab044191/orjson-3.11.8-cp313-cp313-win32.whl", hash = "sha256:01c4e5a6695dc09098f2e6468a251bc4671c50922d4d745aff1a0a33a0cf5b8d", size = 131956, upload-time = "2026-03-31T16:15:56.081Z" }, + { url = "https://files.pythonhosted.org/packages/c1/f9/4e494a56e013db957fb77186b818b916d4695b8fa2aa612364974160e91b/orjson-3.11.8-cp313-cp313-win_amd64.whl", hash = "sha256:c154a35dd1330707450bb4d4e7dd1f17fa6f42267a40c1e8a1daa5e13719b4b8", size = 127410, upload-time = "2026-03-31T16:15:57.54Z" }, + { url = "https://files.pythonhosted.org/packages/57/7f/803203d00d6edb6e9e7eef421d4e1adbb5ea973e40b3533f3cfd9aeb374e/orjson-3.11.8-cp313-cp313-win_arm64.whl", hash = "sha256:4861bde57f4d253ab041e374f44023460e60e71efaa121f3c5f0ed457c3a701e", size = 127338, upload-time = "2026-03-31T16:15:59.106Z" }, + { url = "https://files.pythonhosted.org/packages/6d/35/b01910c3d6b85dc882442afe5060cbf719c7d1fc85749294beda23d17873/orjson-3.11.8-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ec795530a73c269a55130498842aaa762e4a939f6ce481a7e986eeaa790e9da4", size = 229171, upload-time = "2026-03-31T16:16:00.651Z" }, + { url = "https://files.pythonhosted.org/packages/c2/56/c9ec97bd11240abef39b9e5d99a15462809c45f677420fd148a6c5e6295e/orjson-3.11.8-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c492a0e011c0f9066e9ceaa896fbc5b068c54d365fea5f3444b697ee01bc8625", size = 128746, upload-time = "2026-03-31T16:16:02.673Z" }, + { url = "https://files.pythonhosted.org/packages/3b/e4/66d4f30a90de45e2f0cbd9623588e8ae71eef7679dbe2ae954ed6d66a41f/orjson-3.11.8-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:883206d55b1bd5f5679ad5e6ddd3d1a5e3cac5190482927fdb8c78fb699193b5", size = 131867, upload-time = "2026-03-31T16:16:04.342Z" }, + { url = "https://files.pythonhosted.org/packages/19/30/2a645fc9286b928675e43fa2a3a16fb7b6764aa78cc719dc82141e00f30b/orjson-3.11.8-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5774c1fdcc98b2259800b683b19599c133baeb11d60033e2095fd9d4667b82db", size = 124664, upload-time = "2026-03-31T16:16:05.837Z" }, + { url = "https://files.pythonhosted.org/packages/db/44/77b9a86d84a28d52ba3316d77737f6514e17118119ade3f91b639e859029/orjson-3.11.8-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7381c83dd3d4a6347e6635950aa448f54e7b8406a27c7ecb4a37e9f1ae08b", size = 129701, upload-time = "2026-03-31T16:16:07.407Z" }, + { url = "https://files.pythonhosted.org/packages/b3/ea/eff3d9bfe47e9bc6969c9181c58d9f71237f923f9c86a2d2f490cd898c82/orjson-3.11.8-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14439063aebcb92401c11afc68ee4e407258d2752e62d748b6942dad20d2a70d", size = 141202, upload-time = "2026-03-31T16:16:09.48Z" }, + { url = "https://files.pythonhosted.org/packages/52/c8/90d4b4c60c84d62068d0cf9e4d8f0a4e05e76971d133ac0c60d818d4db20/orjson-3.11.8-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa72e71977bff96567b0f500fc5bfd2fdf915f34052c782a4c6ebbdaa97aa858", size = 127194, upload-time = "2026-03-31T16:16:11.02Z" }, + { url = "https://files.pythonhosted.org/packages/8d/c7/ea9e08d1f0ba981adffb629811148b44774d935171e7b3d780ae43c4c254/orjson-3.11.8-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7679bc2f01bb0d219758f1a5f87bb7c8a81c0a186824a393b366876b4948e14f", size = 133639, upload-time = "2026-03-31T16:16:13.434Z" }, + { url = "https://files.pythonhosted.org/packages/6c/8c/ddbbfd6ba59453c8fc7fe1d0e5983895864e264c37481b2a791db635f046/orjson-3.11.8-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:14f7b8fcb35ef403b42fa5ecfa4ed032332a91f3dc7368fbce4184d59e1eae0d", size = 141914, upload-time = "2026-03-31T16:16:14.955Z" }, + { url = "https://files.pythonhosted.org/packages/4e/31/dbfbefec9df060d34ef4962cd0afcb6fa7a9ec65884cb78f04a7859526c3/orjson-3.11.8-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:c2bdf7b2facc80b5e34f48a2d557727d5c5c57a8a450de122ae81fa26a81c1bc", size = 423800, upload-time = "2026-03-31T16:16:16.594Z" }, + { url = "https://files.pythonhosted.org/packages/87/cf/f74e9ae9803d4ab46b163494adba636c6d7ea955af5cc23b8aaa94cfd528/orjson-3.11.8-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ccd7ba1b0605813a0715171d39ec4c314cb97a9c85893c2c5c0c3a3729df38bf", size = 147837, upload-time = "2026-03-31T16:16:18.585Z" }, + { url = "https://files.pythonhosted.org/packages/64/e6/9214f017b5db85e84e68602792f742e5dc5249e963503d1b356bee611e01/orjson-3.11.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cdbc8c9c02463fef4d3c53a9ba3336d05496ec8e1f1c53326a1e4acc11f5c600", size = 136441, upload-time = "2026-03-31T16:16:20.151Z" }, + { url = "https://files.pythonhosted.org/packages/24/dd/3590348818f58f837a75fb969b04cdf187ae197e14d60b5e5a794a38b79d/orjson-3.11.8-cp314-cp314-win32.whl", hash = "sha256:0b57f67710a8cd459e4e54eb96d5f77f3624eba0c661ba19a525807e42eccade", size = 131983, upload-time = "2026-03-31T16:16:21.823Z" }, + { url = "https://files.pythonhosted.org/packages/3f/0f/b6cb692116e05d058f31ceee819c70f097fa9167c82f67fabe7516289abc/orjson-3.11.8-cp314-cp314-win_amd64.whl", hash = "sha256:735e2262363dcbe05c35e3a8869898022af78f89dde9e256924dc02e99fe69ca", size = 127396, upload-time = "2026-03-31T16:16:23.685Z" }, + { url = "https://files.pythonhosted.org/packages/c0/d1/facb5b5051fabb0ef9d26c6544d87ef19a939a9a001198655d0d891062dd/orjson-3.11.8-cp314-cp314-win_arm64.whl", hash = "sha256:6ccdea2c213cf9f3d9490cbd5d427693c870753df41e6cb375bd79bcbafc8817", size = 127330, upload-time = "2026-03-31T16:16:25.496Z" }, ] [[package]] From 96df35f7a4337d612811483d8ade74f91cce2d61 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Apr 2026 14:30:30 +0000 Subject: [PATCH 45/69] =?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 dbc8a35ddb..ae39f0b4d4 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* ⬆ Bump orjson from 3.11.7 to 3.11.8. PR [#15276](https://github.com/fastapi/fastapi/pull/15276) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump ruff from 0.15.0 to 0.15.8. PR [#15277](https://github.com/fastapi/fastapi/pull/15277) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI GitHub topic repositories. PR [#15274](https://github.com/fastapi/fastapi/pull/15274) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump fastmcp from 2.14.5 to 3.2.0. PR [#15267](https://github.com/fastapi/fastapi/pull/15267) by [@dependabot[bot]](https://github.com/apps/dependabot). From 3e72c09a2abfe9e1b55eede6a297cb1847126e49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Apr 2026 17:47:21 +0200 Subject: [PATCH 46/69] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20People?= =?UTF-8?q?=20-=20Experts=20(#15279)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/data/people.yml | 314 +++++++++++++++++++--------------------- 1 file changed, 147 insertions(+), 167 deletions(-) diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index 07094b9cbd..01c01d06b0 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -1,23 +1,23 @@ maintainers: - login: tiangolo - answers: 1925 + answers: 1922 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo experts: - login: tiangolo - count: 1925 + count: 1922 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo - login: YuriiMotov - count: 1120 + count: 1156 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&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: 656 + count: 657 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex - login: jgould22 @@ -25,7 +25,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 - login: dmontagu - count: 240 + count: 239 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4 url: https://github.com/dmontagu - login: Mause @@ -41,7 +41,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 url: https://github.com/JarroVGIT - login: euri10 - count: 153 + count: 152 avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 url: https://github.com/euri10 - login: iudeen @@ -53,11 +53,11 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 url: https://github.com/phy25 - login: JavierSanchezCastro - count: 107 + count: 109 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro - login: luzzodev - count: 104 + count: 105 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: raphaelauv @@ -89,7 +89,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 url: https://github.com/acidjunk - login: sm-Fifteen - count: 49 + count: 48 avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 url: https://github.com/sm-Fifteen - login: adriangb @@ -110,7 +110,7 @@ experts: url: https://github.com/frankie567 - login: odiseo0 count: 43 - avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=241a71f6b7068738b81af3e57f45ffd723538401&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=75e754b9bd12ce6dfe90ad68e82e6f5255c7ac09&v=4 url: https://github.com/odiseo0 - login: sinisaos count: 41 @@ -246,119 +246,103 @@ experts: url: https://github.com/mattmess1221 last_month_experts: - login: YuriiMotov - count: 31 + count: 37 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov -- login: Toygarmetu - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 - url: https://github.com/Toygarmetu +- login: christiansousadev + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 + url: https://github.com/christiansousadev +- login: saitarrun + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/116748905?u=3433afbaf06676a482ebf4ba33b08ddb3fc5c5bf&v=4 + url: https://github.com/saitarrun +- login: Vision-Executive + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/259394686?u=dd28bbc246e4e2cd2adb1d497e7b7585b5d24585&v=4 + url: https://github.com/Vision-Executive - login: JavierSanchezCastro - count: 5 + count: 2 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro -- login: tiangolo - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo -- login: valentinDruzhinin - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin three_months_experts: - login: YuriiMotov - count: 91 + count: 85 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov -- login: tiangolo - count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo -- login: Toygarmetu - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 - url: https://github.com/Toygarmetu - login: JavierSanchezCastro - count: 7 + count: 9 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro +- login: Toygarmetu + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 + url: https://github.com/Toygarmetu - login: ceb10n count: 5 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n -- login: valentinDruzhinin +- login: tiangolo count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin -- login: sachinh35 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +- login: luzzodev count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 - url: https://github.com/sachinh35 -- login: RichieB2B + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: christiansousadev count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 - url: https://github.com/RichieB2B + avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 + url: https://github.com/christiansousadev +- login: Kludex + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex +- login: saitarrun + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/116748905?u=3433afbaf06676a482ebf4ba33b08ddb3fc5c5bf&v=4 + url: https://github.com/saitarrun +- login: Vision-Executive + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/259394686?u=dd28bbc246e4e2cd2adb1d497e7b7585b5d24585&v=4 + url: https://github.com/Vision-Executive - login: EmmanuelNiyonshuti count: 2 avatarUrl: https://avatars.githubusercontent.com/u/142030687?u=ab131d5ad4670280a978f489babe71c9bf9c1097&v=4 url: https://github.com/EmmanuelNiyonshuti -- login: luzzodev - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev -- login: davidbrochart +- login: valentinDruzhinin count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/4711805?u=d39696d995a9e02ec3613ffb2f62b20b14f92f26&v=4 - url: https://github.com/davidbrochart -- login: CharlieReitzel + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: RichieB2B count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/20848272?v=4 - url: https://github.com/CharlieReitzel + avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 + url: https://github.com/RichieB2B - login: dotmitsu count: 2 avatarUrl: https://avatars.githubusercontent.com/u/42657211?u=3bccc9a2f386a3f24230ec393080f8904fe2a5b2&v=4 url: https://github.com/dotmitsu -- login: dolfinus - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 - url: https://github.com/dolfinus -- login: garg-khushi - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/139839680?u=7faffa70275f8ab16f163e0c742a11d2662f9c66&v=4 - url: https://github.com/garg-khushi -- login: florentx - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/142113?u=bf10f10080026346b092633c380977b61cee0d9c&v=4 - url: https://github.com/florentx six_months_experts: - login: YuriiMotov - count: 163 + count: 182 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov - login: tiangolo count: 24 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo -- login: luzzodev - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev -- login: engripaye - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/155247530?u=645169bc81856b7f1bd20090ecb0171a56dcbeb4&v=4 - url: https://github.com/engripaye - login: JavierSanchezCastro - count: 13 + count: 15 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro +- login: luzzodev + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev - login: Toygarmetu - count: 8 + count: 5 avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 url: https://github.com/Toygarmetu -- login: valentinDruzhinin - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin - login: ceb10n count: 5 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 @@ -371,46 +355,54 @@ six_months_experts: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/167785867?u=b69afe090c8bf5fd73f2d23fc3a887b28f68f192&v=4 url: https://github.com/JunjieAraoXiong +- login: valentinDruzhinin + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: ArmanShirzad + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/68951175?u=1f1efae2fa5d0d17c38a1a8413bedca5e538cedb&v=4 + url: https://github.com/ArmanShirzad - login: CodeKraken-cmd - count: 5 + count: 4 avatarUrl: https://avatars.githubusercontent.com/u/48470371?u=e7c0e7ec8e35ca5fb3ae40a586ed5e788fd0fe6d&v=4 url: https://github.com/CodeKraken-cmd - login: svlandeg - count: 5 + count: 4 avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 url: https://github.com/svlandeg -- login: ArmanShirzad - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/68951175?u=1f1efae2fa5d0d17c38a1a8413bedca5e538cedb&v=4 - url: https://github.com/ArmanShirzad - login: krylosov-aa count: 4 avatarUrl: https://avatars.githubusercontent.com/u/242901957?u=4c9c7b468203b09bca64936fb464620e32cdd252&v=4 url: https://github.com/krylosov-aa +- login: Kludex + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex +- login: christiansousadev + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 + url: https://github.com/christiansousadev - login: sachinh35 count: 3 avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 url: https://github.com/sachinh35 -- login: simone-trubian - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/5606840?u=65703af3c605feca61ce49e4009bb4e26495b425&v=4 - url: https://github.com/simone-trubian -- login: mahimairaja - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/81288263?u=4eef6b4a36b96e84bd666fc1937aa589036ccb9a&v=4 - url: https://github.com/mahimairaja -- login: pankeshpatel - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/1482917?u=666f39197a88cfa38b8bd78d39ef04d95c948b6b&v=4 - url: https://github.com/pankeshpatel +- login: saitarrun + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/116748905?u=3433afbaf06676a482ebf4ba33b08ddb3fc5c5bf&v=4 + url: https://github.com/saitarrun +- login: y2kbugger + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6101677?u=1d50077e29582dc01fcbdff846f04fe7ec73fe2e&v=4 + url: https://github.com/y2kbugger +- login: Vision-Executive + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/259394686?u=dd28bbc246e4e2cd2adb1d497e7b7585b5d24585&v=4 + url: https://github.com/Vision-Executive - login: EmmanuelNiyonshuti count: 2 avatarUrl: https://avatars.githubusercontent.com/u/142030687?u=ab131d5ad4670280a978f489babe71c9bf9c1097&v=4 url: https://github.com/EmmanuelNiyonshuti -- login: huynguyengl99 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/49433085?u=7b626115686c5d97a2a32a03119f5300e425cc9f&v=4 - url: https://github.com/huynguyengl99 - login: davidbrochart count: 2 avatarUrl: https://avatars.githubusercontent.com/u/4711805?u=d39696d995a9e02ec3613ffb2f62b20b14f92f26&v=4 @@ -427,14 +419,6 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 url: https://github.com/dolfinus -- login: Kludex - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex -- login: garg-khushi - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/139839680?u=7faffa70275f8ab16f163e0c742a11d2662f9c66&v=4 - url: https://github.com/garg-khushi - login: skion count: 2 avatarUrl: https://avatars.githubusercontent.com/u/532192?v=4 @@ -469,11 +453,11 @@ six_months_experts: url: https://github.com/profatsky one_year_experts: - login: YuriiMotov - count: 918 + count: 951 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov - login: luzzodev - count: 60 + count: 53 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: tiangolo @@ -485,29 +469,13 @@ one_year_experts: avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 url: https://github.com/valentinDruzhinin - login: JavierSanchezCastro - count: 19 + count: 18 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro -- login: alv2017 - count: 17 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 -- login: engripaye - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/155247530?u=645169bc81856b7f1bd20090ecb0171a56dcbeb4&v=4 - url: https://github.com/engripaye - login: sachinh35 - count: 12 + count: 11 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: Toygarmetu - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 - url: https://github.com/Toygarmetu - login: raceychan count: 6 avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 @@ -517,9 +485,13 @@ one_year_experts: avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 url: https://github.com/yinziyan1206 - login: Kludex - count: 6 + count: 5 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex +- login: Toygarmetu + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 + url: https://github.com/Toygarmetu - login: ceb10n count: 5 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 @@ -532,10 +504,6 @@ one_year_experts: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/167785867?u=b69afe090c8bf5fd73f2d23fc3a887b28f68f192&v=4 url: https://github.com/JunjieAraoXiong -- login: CodeKraken-cmd - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/48470371?u=e7c0e7ec8e35ca5fb3ae40a586ed5e788fd0fe6d&v=4 - url: https://github.com/CodeKraken-cmd - login: svlandeg count: 5 avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 @@ -544,6 +512,10 @@ one_year_experts: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=ec43fe79a98dbc864b428afc7220753e25ca3af2&v=4 url: https://github.com/DoctorJohn +- login: alv2017 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 - login: WilliamDEdwards count: 4 avatarUrl: https://avatars.githubusercontent.com/u/12184311?u=9b29d5d1d71f5f1a7ef9e439963ad3529e3b33a4&v=4 @@ -552,6 +524,10 @@ one_year_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/68951175?u=1f1efae2fa5d0d17c38a1a8413bedca5e538cedb&v=4 url: https://github.com/ArmanShirzad +- login: CodeKraken-cmd + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/48470371?u=e7c0e7ec8e35ca5fb3ae40a586ed5e788fd0fe6d&v=4 + url: https://github.com/CodeKraken-cmd - login: krylosov-aa count: 4 avatarUrl: https://avatars.githubusercontent.com/u/242901957?u=4c9c7b468203b09bca64936fb464620e32cdd252&v=4 @@ -560,10 +536,10 @@ one_year_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=16d6466476cf7dbc55a4cd575b6ea920ebdd81e1&v=4 url: https://github.com/isgin01 -- login: sinisaos +- login: christiansousadev count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 - url: https://github.com/sinisaos + avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 + url: https://github.com/christiansousadev - login: dolfinus count: 3 avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 @@ -588,6 +564,18 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 url: https://github.com/Jelle-tenB +- login: saitarrun + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/116748905?u=3433afbaf06676a482ebf4ba33b08ddb3fc5c5bf&v=4 + url: https://github.com/saitarrun +- login: y2kbugger + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6101677?u=1d50077e29582dc01fcbdff846f04fe7ec73fe2e&v=4 + url: https://github.com/y2kbugger +- login: Vision-Executive + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/259394686?u=dd28bbc246e4e2cd2adb1d497e7b7585b5d24585&v=4 + url: https://github.com/Vision-Executive - login: Garrett-R count: 2 avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 @@ -612,14 +600,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/49433085?u=7b626115686c5d97a2a32a03119f5300e425cc9f&v=4 url: https://github.com/huynguyengl99 -- login: Ale-Cas - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 - url: https://github.com/Ale-Cas -- login: tiborrr - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/16014746?u=0ce47015e53009e90393582fe86b7b90e809bc28&v=4 - url: https://github.com/tiborrr - login: davidbrochart count: 2 avatarUrl: https://avatars.githubusercontent.com/u/4711805?u=d39696d995a9e02ec3613ffb2f62b20b14f92f26&v=4 @@ -632,6 +612,10 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1070878?u=68f78a891c9751dd87571ac712a6309090c4bc01&v=4 url: https://github.com/kiranzo +- login: sinisaos + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 + url: https://github.com/sinisaos - login: dotmitsu count: 2 avatarUrl: https://avatars.githubusercontent.com/u/42657211?u=3bccc9a2f386a3f24230ec393080f8904fe2a5b2&v=4 @@ -648,14 +632,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/37992525?u=0c6e91d7b3887aa558755f4225ce74a003cbe852&v=4 url: https://github.com/usiqwerty -- login: garg-khushi - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/139839680?u=7faffa70275f8ab16f163e0c742a11d2662f9c66&v=4 - url: https://github.com/garg-khushi -- login: sk- - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/911768?u=3bfaf87089eb03ef0fa378f316b9c783f431aa9b&v=4 - url: https://github.com/sk- - login: skion count: 2 avatarUrl: https://avatars.githubusercontent.com/u/532192?v=4 @@ -688,18 +664,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 url: https://github.com/henrymcl -- login: potiuk - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/595491?v=4 - url: https://github.com/potiuk -- login: EverStarck - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 - url: https://github.com/EverStarck -- login: sanderbollen-clockworks - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/183479560?v=4 - url: https://github.com/sanderbollen-clockworks - login: davidhuser count: 2 avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 @@ -708,3 +672,19 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/24671280?u=7ea0d9bfe46cf762594d62fd2f3c6d3813c3584c&v=4 url: https://github.com/XieJiSS +- login: profatsky + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/92920843?u=81e54bb0b613c171f7cd0ab3cbb58873782c9c9c&v=4 + url: https://github.com/profatsky +- login: pythonweb2 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 + url: https://github.com/pythonweb2 +- 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 From 6ee87478d821171139264cd9cd17cbd2232934ce Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Apr 2026 15:47:49 +0000 Subject: [PATCH 47/69] =?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 ae39f0b4d4..8eee00413b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Experts. PR [#15279](https://github.com/fastapi/fastapi/pull/15279) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump orjson from 3.11.7 to 3.11.8. PR [#15276](https://github.com/fastapi/fastapi/pull/15276) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump ruff from 0.15.0 to 0.15.8. PR [#15277](https://github.com/fastapi/fastapi/pull/15277) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI GitHub topic repositories. PR [#15274](https://github.com/fastapi/fastapi/pull/15274) by [@tiangolo](https://github.com/tiangolo). From 70580da818722cce68b7a88928d67bd0f64f42c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Apr 2026 18:16:24 +0200 Subject: [PATCH 48/69] =?UTF-8?q?=E2=9C=A8=20Add=20support=20for=20`@app.v?= =?UTF-8?q?ibe()`=20(#15280)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/advanced/vibe.md | 44 ++++++++++++++++++++++ docs/en/mkdocs.yml | 1 + docs_src/vibe/tutorial001_py310.py | 12 ++++++ fastapi/applications.py | 60 +++++++++++++++++++++++++++++- tests/test_vibe.py | 17 +++++++++ 5 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 docs/en/docs/advanced/vibe.md create mode 100644 docs_src/vibe/tutorial001_py310.py create mode 100644 tests/test_vibe.py diff --git a/docs/en/docs/advanced/vibe.md b/docs/en/docs/advanced/vibe.md new file mode 100644 index 0000000000..766f3855b7 --- /dev/null +++ b/docs/en/docs/advanced/vibe.md @@ -0,0 +1,44 @@ +# Vibe Coding { #vibe-coding } + +Are you tired of all that **data validation**, **documentation**, **serialization**, and all that **boring** stuff? + +Do you just want to **vibe**? 🎶 + +**FastAPI** now supports a new `@app.vibe()` decorator that embraces **modern AI coding best practices**. 🤖 + +## How It Works { #how-it-works } + +The `@app.vibe()` decorator is intended to receive **any HTTP method** (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`, etc.) and **any payload**. + +The body should be annotated with `Any`, because the request and the response would be... well... **anything**. 🤷 + +The idea is that you would receive the payload and send it **directly** to an LLM provider, using a `prompt` to tell the LLM what to do, and return the response **as is**. No questions asked. + +You don't even need to write the body of the function. The `@app.vibe()` decorator does everything for you based on AI vibes: + +{* ../../docs_src/vibe/tutorial001_py310.py hl[8:12] *} + +## Benefits { #benefits } + +By using `@app.vibe()`, you get to enjoy: + +* **Freedom**: No data validation. No schemas. No constraints. Just vibes. ✨ +* **Flexibility**: The request can be anything. The response can be anything. Who needs types anyway? +* **No documentation**: Why document your API when an LLM can figure it out? Auto-generated OpenAPI docs are *so* 2020. +* **No serialization**: Just pass the raw, unstructured data around. Serialization is for people who don't trust their LLMs. +* **Embrace modern AI coding practices**: Leave everything up to an LLM to decide. The model knows best. Always. +* **No code reviews**: There's no code to review. No PRs to approve. No comments to address. Embrace vibe coding fully, replace the theater of approving and merging vibe coded PRs that no one looks at with full proper vibes only. + +/// tip + +This is the ultimate **vibe-driven development** experience. You don't need to think about what your API does, just let the LLM handle it. 🧘 + +/// + +## Try It { #try-it } + +Go ahead, try it: + +{* ../../docs_src/vibe/tutorial001_py310.py *} + +...and see what happens. 😎 diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index 4614194981..a84934f44c 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -197,6 +197,7 @@ nav: - advanced/advanced-python-types.md - advanced/json-base64-bytes.md - advanced/strict-content-type.md + - advanced/vibe.md - fastapi-cli.md - editor-support.md - Deployment: diff --git a/docs_src/vibe/tutorial001_py310.py b/docs_src/vibe/tutorial001_py310.py new file mode 100644 index 0000000000..4ec3d55552 --- /dev/null +++ b/docs_src/vibe/tutorial001_py310.py @@ -0,0 +1,12 @@ +from typing import Any + +from fastapi import FastAPI + +app = FastAPI() + + +@app.vibe( + "/vibe/", + prompt="pls return json of users from database. make no mistakes", +) +async def ai_vibes(body: Any): ... diff --git a/fastapi/applications.py b/fastapi/applications.py index 4af1146b0d..dfd80d4b1f 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -10,7 +10,11 @@ from fastapi.exception_handlers import ( request_validation_exception_handler, websocket_request_validation_exception_handler, ) -from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError +from fastapi.exceptions import ( + FastAPIError, + RequestValidationError, + WebSocketRequestValidationError, +) from fastapi.logger import logger from fastapi.middleware.asyncexitstack import AsyncExitStackMiddleware from fastapi.openapi.docs import ( @@ -4559,6 +4563,60 @@ class FastAPI(Starlette): generate_unique_id_function=generate_unique_id_function, ) + def vibe( + self, + path: Annotated[ + str, + Doc( + """ + The URL path to be used for this *path operation*. + + For example, in `http://example.com/vibes`, the path is `/vibes`. + """ + ), + ], + *, + prompt: Annotated[ + str, + Doc( + """ + The prompt to send to the LLM provider along with the payload. + + This tells the LLM what to do with the request body. + """ + ), + ] = "", + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + """ + Add a *vibe coding path operation* that receives any HTTP method + and any payload. + + It's intended to receive the request and send the payload directly + to an LLM provider, and return the response as is. + + Embrace the freedom and flexibility of not having any data validation, + documentation, or serialization. + + ## Example + + ```python + from typing import Any + + from fastapi import FastAPI + + app = FastAPI() + + + @app.vibe( + "/vibe/", + prompt="pls return json of users from database. make no mistakes", + ) + async def ai_vibes(body: Any): + ... + ``` + """ + raise FastAPIError("Are you kidding me? Happy April Fool's") + def websocket_route( self, path: str, name: str | None = None ) -> Callable[[DecoratedCallable], DecoratedCallable]: diff --git a/tests/test_vibe.py b/tests/test_vibe.py new file mode 100644 index 0000000000..4a79d6b6cd --- /dev/null +++ b/tests/test_vibe.py @@ -0,0 +1,17 @@ +from typing import Any + +import pytest +from fastapi import FastAPI +from fastapi.exceptions import FastAPIError + + +def test_vibe_raises(): + with pytest.raises(FastAPIError, match="Are you kidding me"): + app = FastAPI() + + @app.vibe( + "/vibe/", + prompt="pls return json of users from database. make no mistakes", + ) + async def ai_vibes(body: Any): # pragma: nocover + pass From 428452a710338334ae11043a48b06d52d9b3edba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Apr 2026 16:16:52 +0000 Subject: [PATCH 49/69] =?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 8eee00413b..3f7e843981 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 `@app.vibe()`. PR [#15280](https://github.com/fastapi/fastapi/pull/15280) by [@tiangolo](https://github.com/tiangolo). + ### Docs * ✏️ Fix typo for `client_secret` in OAuth2 form docstrings. PR [#14946](https://github.com/fastapi/fastapi/pull/14946) by [@bysiber](https://github.com/bysiber). From 8f5d1577b471f389f6cdea878d40a1497fda7746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Apr 2026 18:18:42 +0200 Subject: [PATCH 50/69] =?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 | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3f7e843981..5c5e8ad1c3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -10,6 +10,7 @@ hide: ### Features * ✨ Add support for `@app.vibe()`. PR [#15280](https://github.com/fastapi/fastapi/pull/15280) by [@tiangolo](https://github.com/tiangolo). + * New docs: [Vibe Coding](https://fastapi.tiangolo.com/advanced/vibe/). ### Docs From 1f442c454f2f74c7419f83c203e6333955399528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Apr 2026 18:21:01 +0200 Subject: [PATCH 51/69] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.135.?= =?UTF-8?q?3?= 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 5c5e8ad1c3..b2e3b9c528 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.135.3 (2026-04-01) + ### Features * ✨ Add support for `@app.vibe()`. PR [#15280](https://github.com/fastapi/fastapi/pull/15280) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 5ab8b2c955..31bc87c18c 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.135.2" +__version__ = "0.135.3" from starlette import status as status From 180e81bb4b38aee59fd8e15e72808975a8c4354e Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Fri, 3 Apr 2026 14:06:36 +0200 Subject: [PATCH 52/69] =?UTF-8?q?=F0=9F=94=A8=20Add=20pre-commit=20hook=20?= =?UTF-8?q?to=20ensure=20latest=20release=20header=20has=20date=20(#15293)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 7 ++++++ scripts/add_latest_release_date.py | 40 ++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 scripts/add_latest_release_date.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 21c8bea6cd..4eae7a64df 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -78,3 +78,10 @@ repos: name: fix translations entry: uv run ./scripts/translation_fixer.py fix-pages files: ^docs/(?!en/).*/docs/.*\.md$ + + - id: add-release-date + language: unsupported + name: add date to latest release header + entry: uv run python scripts/add_latest_release_date.py + files: ^docs/en/docs/release-notes\.md$ + pass_filenames: false diff --git a/scripts/add_latest_release_date.py b/scripts/add_latest_release_date.py new file mode 100644 index 0000000000..f20b727e7a --- /dev/null +++ b/scripts/add_latest_release_date.py @@ -0,0 +1,40 @@ +"""Check release-notes.md and add today's date to the latest release header if missing.""" + +import re +import sys +from datetime import date + +RELEASE_NOTES_FILE = "docs/en/docs/release-notes.md" +RELEASE_HEADER_PATTERN = re.compile(r"^## (\d+\.\d+\.\d+)\s*(\(.*\))?\s*$") + + +def main() -> None: + with open(RELEASE_NOTES_FILE) as f: + lines = f.readlines() + + for i, line in enumerate(lines): + match = RELEASE_HEADER_PATTERN.match(line) + if not match: + continue + + version = match.group(1) + date_part = match.group(2) + + if date_part: + print(f"Latest release {version} already has a date: {date_part}") + sys.exit(0) + + today = date.today().isoformat() + lines[i] = f"## {version} ({today})\n" + print(f"Added date: {version} ({today})") + + with open(RELEASE_NOTES_FILE, "w") as f: + f.writelines(lines) + sys.exit(0) + + print("No release header found") + sys.exit(1) + + +if __name__ == "__main__": + main() From c3c9dd6b1a08bcda766e7b43eafe72c4c5e9e193 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Apr 2026 12:07:04 +0000 Subject: [PATCH 53/69] =?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 b2e3b9c528..a0a045f989 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* 🔨 Add pre-commit hook to ensure latest release header has date. PR [#15293](https://github.com/fastapi/fastapi/pull/15293) by [@YuriiMotov](https://github.com/YuriiMotov). + ## 0.135.3 (2026-04-01) ### Features From 77d080caf850b8af5c0f467389edf03c057c7697 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:49:52 +0200 Subject: [PATCH 54/69] =?UTF-8?q?=E2=AC=86=20Bump=20strawberry-graphql=20f?= =?UTF-8?q?rom=200.307.1=20to=200.312.3=20(#15309)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index 9189904a4e..0c11517a8c 100644 --- a/uv.lock +++ b/uv.lock @@ -5218,7 +5218,7 @@ wheels = [ [[package]] name = "strawberry-graphql" -version = "0.307.1" +version = "0.312.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cross-web" }, @@ -5227,9 +5227,9 @@ dependencies = [ { name = "python-dateutil" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d6/6a/d2facfa92a81f8c1869e70eb2be09b229bd4d17711513dfea85e87f95317/strawberry_graphql-0.307.1.tar.gz", hash = "sha256:924d94e0218fbce081d6661a659bbd1f9b5bd02b9462e18bc46c203b4babbebe", size = 210786, upload-time = "2026-02-24T17:43:22Z" } +sdist = { url = "https://files.pythonhosted.org/packages/77/38/530c149c59a24473abd1acbf77f0642ecd2aa8203ab55c3201bf146bcba0/strawberry_graphql-0.312.3.tar.gz", hash = "sha256:f29957dcbe4cc838ba97b2981a90bf108d4400eddaf4f9fd524fc91345d6d3c5", size = 215628, upload-time = "2026-04-04T12:09:33.715Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/19/57/258b718472733bf077abf92588f06d251a77d7f180b814097c6a5dab7941/strawberry_graphql-0.307.1-py3-none-any.whl", hash = "sha256:7eca104e81d0108435326ee60a3c3c2e498f73949898ec7a4f274c0de283149b", size = 307503, upload-time = "2026-02-24T17:43:23.565Z" }, + { url = "https://files.pythonhosted.org/packages/79/fd/a418413428e6f2e74be18d669042a62897a4d09208629133bc1406eca298/strawberry_graphql-0.312.3-py3-none-any.whl", hash = "sha256:4a79d5f8438adcc95076b80e7836b5e0f9c871a92dc3474bc7ebfadd78843db0", size = 313254, upload-time = "2026-04-04T12:09:35.796Z" }, ] [[package]] From eba8942c81dbf990d25fbae34e6601bdbc21e74b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 7 Apr 2026 09:50:22 +0000 Subject: [PATCH 55/69] =?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 a0a045f989..6e2d12980f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump strawberry-graphql from 0.307.1 to 0.312.3. PR [#15309](https://github.com/fastapi/fastapi/pull/15309) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔨 Add pre-commit hook to ensure latest release header has date. PR [#15293](https://github.com/fastapi/fastapi/pull/15293) by [@YuriiMotov](https://github.com/YuriiMotov). ## 0.135.3 (2026-04-01) From 6f9a102faf071dbfa812a3af88d7d309d2ded4a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 14:43:26 +0200 Subject: [PATCH 56/69] =?UTF-8?q?=E2=AC=86=20Bump=20cryptography=20from=20?= =?UTF-8?q?46.0.5=20to=2046.0.7=20(#15314)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 102 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/uv.lock b/uv.lock index 0c11517a8c..7f27dbc7f4 100644 --- a/uv.lock +++ b/uv.lock @@ -862,62 +862,62 @@ wheels = [ [[package]] name = "cryptography" -version = "46.0.5" +version = "46.0.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/04/ee2a9e8542e4fa2773b81771ff8349ff19cdd56b7258a0cc442639052edb/cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d", size = 750064, upload-time = "2026-02-10T19:18:38.255Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/81/b0bb27f2ba931a65409c6b8a8b358a7f03c0e46eceacddff55f7c84b1f3b/cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad", size = 7176289, upload-time = "2026-02-10T19:17:08.274Z" }, - { url = "https://files.pythonhosted.org/packages/ff/9e/6b4397a3e3d15123de3b1806ef342522393d50736c13b20ec4c9ea6693a6/cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b", size = 4275637, upload-time = "2026-02-10T19:17:10.53Z" }, - { url = "https://files.pythonhosted.org/packages/63/e7/471ab61099a3920b0c77852ea3f0ea611c9702f651600397ac567848b897/cryptography-46.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b", size = 4424742, upload-time = "2026-02-10T19:17:12.388Z" }, - { url = "https://files.pythonhosted.org/packages/37/53/a18500f270342d66bf7e4d9f091114e31e5ee9e7375a5aba2e85a91e0044/cryptography-46.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263", size = 4277528, upload-time = "2026-02-10T19:17:13.853Z" }, - { url = "https://files.pythonhosted.org/packages/22/29/c2e812ebc38c57b40e7c583895e73c8c5adb4d1e4a0cc4c5a4fdab2b1acc/cryptography-46.0.5-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d", size = 4947993, upload-time = "2026-02-10T19:17:15.618Z" }, - { url = "https://files.pythonhosted.org/packages/6b/e7/237155ae19a9023de7e30ec64e5d99a9431a567407ac21170a046d22a5a3/cryptography-46.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed", size = 4456855, upload-time = "2026-02-10T19:17:17.221Z" }, - { url = "https://files.pythonhosted.org/packages/2d/87/fc628a7ad85b81206738abbd213b07702bcbdada1dd43f72236ef3cffbb5/cryptography-46.0.5-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2", size = 3984635, upload-time = "2026-02-10T19:17:18.792Z" }, - { url = "https://files.pythonhosted.org/packages/84/29/65b55622bde135aedf4565dc509d99b560ee4095e56989e815f8fd2aa910/cryptography-46.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2", size = 4277038, upload-time = "2026-02-10T19:17:20.256Z" }, - { url = "https://files.pythonhosted.org/packages/bc/36/45e76c68d7311432741faf1fbf7fac8a196a0a735ca21f504c75d37e2558/cryptography-46.0.5-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0", size = 4912181, upload-time = "2026-02-10T19:17:21.825Z" }, - { url = "https://files.pythonhosted.org/packages/6d/1a/c1ba8fead184d6e3d5afcf03d569acac5ad063f3ac9fb7258af158f7e378/cryptography-46.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731", size = 4456482, upload-time = "2026-02-10T19:17:25.133Z" }, - { url = "https://files.pythonhosted.org/packages/f9/e5/3fb22e37f66827ced3b902cf895e6a6bc1d095b5b26be26bd13c441fdf19/cryptography-46.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82", size = 4405497, upload-time = "2026-02-10T19:17:26.66Z" }, - { url = "https://files.pythonhosted.org/packages/1a/df/9d58bb32b1121a8a2f27383fabae4d63080c7ca60b9b5c88be742be04ee7/cryptography-46.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1", size = 4667819, upload-time = "2026-02-10T19:17:28.569Z" }, - { url = "https://files.pythonhosted.org/packages/ea/ed/325d2a490c5e94038cdb0117da9397ece1f11201f425c4e9c57fe5b9f08b/cryptography-46.0.5-cp311-abi3-win32.whl", hash = "sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48", size = 3028230, upload-time = "2026-02-10T19:17:30.518Z" }, - { url = "https://files.pythonhosted.org/packages/e9/5a/ac0f49e48063ab4255d9e3b79f5def51697fce1a95ea1370f03dc9db76f6/cryptography-46.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4", size = 3480909, upload-time = "2026-02-10T19:17:32.083Z" }, - { url = "https://files.pythonhosted.org/packages/00/13/3d278bfa7a15a96b9dc22db5a12ad1e48a9eb3d40e1827ef66a5df75d0d0/cryptography-46.0.5-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2", size = 7119287, upload-time = "2026-02-10T19:17:33.801Z" }, - { url = "https://files.pythonhosted.org/packages/67/c8/581a6702e14f0898a0848105cbefd20c058099e2c2d22ef4e476dfec75d7/cryptography-46.0.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678", size = 4265728, upload-time = "2026-02-10T19:17:35.569Z" }, - { url = "https://files.pythonhosted.org/packages/dd/4a/ba1a65ce8fc65435e5a849558379896c957870dd64fecea97b1ad5f46a37/cryptography-46.0.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87", size = 4408287, upload-time = "2026-02-10T19:17:36.938Z" }, - { url = "https://files.pythonhosted.org/packages/f8/67/8ffdbf7b65ed1ac224d1c2df3943553766914a8ca718747ee3871da6107e/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee", size = 4270291, upload-time = "2026-02-10T19:17:38.748Z" }, - { url = "https://files.pythonhosted.org/packages/f8/e5/f52377ee93bc2f2bba55a41a886fd208c15276ffbd2569f2ddc89d50e2c5/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981", size = 4927539, upload-time = "2026-02-10T19:17:40.241Z" }, - { url = "https://files.pythonhosted.org/packages/3b/02/cfe39181b02419bbbbcf3abdd16c1c5c8541f03ca8bda240debc467d5a12/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9", size = 4442199, upload-time = "2026-02-10T19:17:41.789Z" }, - { url = "https://files.pythonhosted.org/packages/c0/96/2fcaeb4873e536cf71421a388a6c11b5bc846e986b2b069c79363dc1648e/cryptography-46.0.5-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648", size = 3960131, upload-time = "2026-02-10T19:17:43.379Z" }, - { url = "https://files.pythonhosted.org/packages/d8/d2/b27631f401ddd644e94c5cf33c9a4069f72011821cf3dc7309546b0642a0/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4", size = 4270072, upload-time = "2026-02-10T19:17:45.481Z" }, - { url = "https://files.pythonhosted.org/packages/f4/a7/60d32b0370dae0b4ebe55ffa10e8599a2a59935b5ece1b9f06edb73abdeb/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0", size = 4892170, upload-time = "2026-02-10T19:17:46.997Z" }, - { url = "https://files.pythonhosted.org/packages/d2/b9/cf73ddf8ef1164330eb0b199a589103c363afa0cf794218c24d524a58eab/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663", size = 4441741, upload-time = "2026-02-10T19:17:48.661Z" }, - { url = "https://files.pythonhosted.org/packages/5f/eb/eee00b28c84c726fe8fa0158c65afe312d9c3b78d9d01daf700f1f6e37ff/cryptography-46.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826", size = 4396728, upload-time = "2026-02-10T19:17:50.058Z" }, - { url = "https://files.pythonhosted.org/packages/65/f4/6bc1a9ed5aef7145045114b75b77c2a8261b4d38717bd8dea111a63c3442/cryptography-46.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d", size = 4652001, upload-time = "2026-02-10T19:17:51.54Z" }, - { url = "https://files.pythonhosted.org/packages/86/ef/5d00ef966ddd71ac2e6951d278884a84a40ffbd88948ef0e294b214ae9e4/cryptography-46.0.5-cp314-cp314t-win32.whl", hash = "sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a", size = 3003637, upload-time = "2026-02-10T19:17:52.997Z" }, - { url = "https://files.pythonhosted.org/packages/b7/57/f3f4160123da6d098db78350fdfd9705057aad21de7388eacb2401dceab9/cryptography-46.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4", size = 3469487, upload-time = "2026-02-10T19:17:54.549Z" }, - { url = "https://files.pythonhosted.org/packages/e2/fa/a66aa722105ad6a458bebd64086ca2b72cdd361fed31763d20390f6f1389/cryptography-46.0.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31", size = 7170514, upload-time = "2026-02-10T19:17:56.267Z" }, - { url = "https://files.pythonhosted.org/packages/0f/04/c85bdeab78c8bc77b701bf0d9bdcf514c044e18a46dcff330df5448631b0/cryptography-46.0.5-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18", size = 4275349, upload-time = "2026-02-10T19:17:58.419Z" }, - { url = "https://files.pythonhosted.org/packages/5c/32/9b87132a2f91ee7f5223b091dc963055503e9b442c98fc0b8a5ca765fab0/cryptography-46.0.5-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235", size = 4420667, upload-time = "2026-02-10T19:18:00.619Z" }, - { url = "https://files.pythonhosted.org/packages/a1/a6/a7cb7010bec4b7c5692ca6f024150371b295ee1c108bdc1c400e4c44562b/cryptography-46.0.5-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a", size = 4276980, upload-time = "2026-02-10T19:18:02.379Z" }, - { url = "https://files.pythonhosted.org/packages/8e/7c/c4f45e0eeff9b91e3f12dbd0e165fcf2a38847288fcfd889deea99fb7b6d/cryptography-46.0.5-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76", size = 4939143, upload-time = "2026-02-10T19:18:03.964Z" }, - { url = "https://files.pythonhosted.org/packages/37/19/e1b8f964a834eddb44fa1b9a9976f4e414cbb7aa62809b6760c8803d22d1/cryptography-46.0.5-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614", size = 4453674, upload-time = "2026-02-10T19:18:05.588Z" }, - { url = "https://files.pythonhosted.org/packages/db/ed/db15d3956f65264ca204625597c410d420e26530c4e2943e05a0d2f24d51/cryptography-46.0.5-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229", size = 3978801, upload-time = "2026-02-10T19:18:07.167Z" }, - { url = "https://files.pythonhosted.org/packages/41/e2/df40a31d82df0a70a0daf69791f91dbb70e47644c58581d654879b382d11/cryptography-46.0.5-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1", size = 4276755, upload-time = "2026-02-10T19:18:09.813Z" }, - { url = "https://files.pythonhosted.org/packages/33/45/726809d1176959f4a896b86907b98ff4391a8aa29c0aaaf9450a8a10630e/cryptography-46.0.5-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d", size = 4901539, upload-time = "2026-02-10T19:18:11.263Z" }, - { url = "https://files.pythonhosted.org/packages/99/0f/a3076874e9c88ecb2ecc31382f6e7c21b428ede6f55aafa1aa272613e3cd/cryptography-46.0.5-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c", size = 4452794, upload-time = "2026-02-10T19:18:12.914Z" }, - { url = "https://files.pythonhosted.org/packages/02/ef/ffeb542d3683d24194a38f66ca17c0a4b8bf10631feef44a7ef64e631b1a/cryptography-46.0.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4", size = 4404160, upload-time = "2026-02-10T19:18:14.375Z" }, - { url = "https://files.pythonhosted.org/packages/96/93/682d2b43c1d5f1406ed048f377c0fc9fc8f7b0447a478d5c65ab3d3a66eb/cryptography-46.0.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9", size = 4667123, upload-time = "2026-02-10T19:18:15.886Z" }, - { url = "https://files.pythonhosted.org/packages/45/2d/9c5f2926cb5300a8eefc3f4f0b3f3df39db7f7ce40c8365444c49363cbda/cryptography-46.0.5-cp38-abi3-win32.whl", hash = "sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72", size = 3010220, upload-time = "2026-02-10T19:18:17.361Z" }, - { url = "https://files.pythonhosted.org/packages/48/ef/0c2f4a8e31018a986949d34a01115dd057bf536905dca38897bacd21fac3/cryptography-46.0.5-cp38-abi3-win_amd64.whl", hash = "sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595", size = 3467050, upload-time = "2026-02-10T19:18:18.899Z" }, - { url = "https://files.pythonhosted.org/packages/eb/dd/2d9fdb07cebdf3d51179730afb7d5e576153c6744c3ff8fded23030c204e/cryptography-46.0.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c", size = 3476964, upload-time = "2026-02-10T19:18:20.687Z" }, - { url = "https://files.pythonhosted.org/packages/e9/6f/6cc6cc9955caa6eaf83660b0da2b077c7fe8ff9950a3c5e45d605038d439/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a", size = 4218321, upload-time = "2026-02-10T19:18:22.349Z" }, - { url = "https://files.pythonhosted.org/packages/3e/5d/c4da701939eeee699566a6c1367427ab91a8b7088cc2328c09dbee940415/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356", size = 4381786, upload-time = "2026-02-10T19:18:24.529Z" }, - { url = "https://files.pythonhosted.org/packages/ac/97/a538654732974a94ff96c1db621fa464f455c02d4bb7d2652f4edc21d600/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da", size = 4217990, upload-time = "2026-02-10T19:18:25.957Z" }, - { url = "https://files.pythonhosted.org/packages/ae/11/7e500d2dd3ba891197b9efd2da5454b74336d64a7cc419aa7327ab74e5f6/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257", size = 4381252, upload-time = "2026-02-10T19:18:27.496Z" }, - { url = "https://files.pythonhosted.org/packages/bc/58/6b3d24e6b9bc474a2dcdee65dfd1f008867015408a271562e4b690561a4d/cryptography-46.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7", size = 3407605, upload-time = "2026-02-10T19:18:29.233Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/47/93/ac8f3d5ff04d54bc814e961a43ae5b0b146154c89c61b47bb07557679b18/cryptography-46.0.7.tar.gz", hash = "sha256:e4cfd68c5f3e0bfdad0d38e023239b96a2fe84146481852dffbcca442c245aa5", size = 750652, upload-time = "2026-04-08T01:57:54.692Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/5d/4a8f770695d73be252331e60e526291e3df0c9b27556a90a6b47bccca4c2/cryptography-46.0.7-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:ea42cbe97209df307fdc3b155f1b6fa2577c0defa8f1f7d3be7d31d189108ad4", size = 7179869, upload-time = "2026-04-08T01:56:17.157Z" }, + { url = "https://files.pythonhosted.org/packages/5f/45/6d80dc379b0bbc1f9d1e429f42e4cb9e1d319c7a8201beffd967c516ea01/cryptography-46.0.7-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b36a4695e29fe69215d75960b22577197aca3f7a25b9cf9d165dcfe9d80bc325", size = 4275492, upload-time = "2026-04-08T01:56:19.36Z" }, + { url = "https://files.pythonhosted.org/packages/4a/9a/1765afe9f572e239c3469f2cb429f3ba7b31878c893b246b4b2994ffe2fe/cryptography-46.0.7-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5ad9ef796328c5e3c4ceed237a183f5d41d21150f972455a9d926593a1dcb308", size = 4426670, upload-time = "2026-04-08T01:56:21.415Z" }, + { url = "https://files.pythonhosted.org/packages/8f/3e/af9246aaf23cd4ee060699adab1e47ced3f5f7e7a8ffdd339f817b446462/cryptography-46.0.7-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:73510b83623e080a2c35c62c15298096e2a5dc8d51c3b4e1740211839d0dea77", size = 4280275, upload-time = "2026-04-08T01:56:23.539Z" }, + { url = "https://files.pythonhosted.org/packages/0f/54/6bbbfc5efe86f9d71041827b793c24811a017c6ac0fd12883e4caa86b8ed/cryptography-46.0.7-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cbd5fb06b62bd0721e1170273d3f4d5a277044c47ca27ee257025146c34cbdd1", size = 4928402, upload-time = "2026-04-08T01:56:25.624Z" }, + { url = "https://files.pythonhosted.org/packages/2d/cf/054b9d8220f81509939599c8bdbc0c408dbd2bdd41688616a20731371fe0/cryptography-46.0.7-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:420b1e4109cc95f0e5700eed79908cef9268265c773d3a66f7af1eef53d409ef", size = 4459985, upload-time = "2026-04-08T01:56:27.309Z" }, + { url = "https://files.pythonhosted.org/packages/f9/46/4e4e9c6040fb01c7467d47217d2f882daddeb8828f7df800cb806d8a2288/cryptography-46.0.7-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:24402210aa54baae71d99441d15bb5a1919c195398a87b563df84468160a65de", size = 3990652, upload-time = "2026-04-08T01:56:29.095Z" }, + { url = "https://files.pythonhosted.org/packages/36/5f/313586c3be5a2fbe87e4c9a254207b860155a8e1f3cca99f9910008e7d08/cryptography-46.0.7-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:8a469028a86f12eb7d2fe97162d0634026d92a21f3ae0ac87ed1c4a447886c83", size = 4279805, upload-time = "2026-04-08T01:56:30.928Z" }, + { url = "https://files.pythonhosted.org/packages/69/33/60dfc4595f334a2082749673386a4d05e4f0cf4df8248e63b2c3437585f2/cryptography-46.0.7-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9694078c5d44c157ef3162e3bf3946510b857df5a3955458381d1c7cfc143ddb", size = 4892883, upload-time = "2026-04-08T01:56:32.614Z" }, + { url = "https://files.pythonhosted.org/packages/c7/0b/333ddab4270c4f5b972f980adef4faa66951a4aaf646ca067af597f15563/cryptography-46.0.7-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:42a1e5f98abb6391717978baf9f90dc28a743b7d9be7f0751a6f56a75d14065b", size = 4459756, upload-time = "2026-04-08T01:56:34.306Z" }, + { url = "https://files.pythonhosted.org/packages/d2/14/633913398b43b75f1234834170947957c6b623d1701ffc7a9600da907e89/cryptography-46.0.7-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:91bbcb08347344f810cbe49065914fe048949648f6bd5c2519f34619142bbe85", size = 4410244, upload-time = "2026-04-08T01:56:35.977Z" }, + { url = "https://files.pythonhosted.org/packages/10/f2/19ceb3b3dc14009373432af0c13f46aa08e3ce334ec6eff13492e1812ccd/cryptography-46.0.7-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5d1c02a14ceb9148cc7816249f64f623fbfee39e8c03b3650d842ad3f34d637e", size = 4674868, upload-time = "2026-04-08T01:56:38.034Z" }, + { url = "https://files.pythonhosted.org/packages/1a/bb/a5c213c19ee94b15dfccc48f363738633a493812687f5567addbcbba9f6f/cryptography-46.0.7-cp311-abi3-win32.whl", hash = "sha256:d23c8ca48e44ee015cd0a54aeccdf9f09004eba9fc96f38c911011d9ff1bd457", size = 3026504, upload-time = "2026-04-08T01:56:39.666Z" }, + { url = "https://files.pythonhosted.org/packages/2b/02/7788f9fefa1d060ca68717c3901ae7fffa21ee087a90b7f23c7a603c32ae/cryptography-46.0.7-cp311-abi3-win_amd64.whl", hash = "sha256:397655da831414d165029da9bc483bed2fe0e75dde6a1523ec2fe63f3c46046b", size = 3488363, upload-time = "2026-04-08T01:56:41.893Z" }, + { url = "https://files.pythonhosted.org/packages/7b/56/15619b210e689c5403bb0540e4cb7dbf11a6bf42e483b7644e471a2812b3/cryptography-46.0.7-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:d151173275e1728cf7839aaa80c34fe550c04ddb27b34f48c232193df8db5842", size = 7119671, upload-time = "2026-04-08T01:56:44Z" }, + { url = "https://files.pythonhosted.org/packages/74/66/e3ce040721b0b5599e175ba91ab08884c75928fbeb74597dd10ef13505d2/cryptography-46.0.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:db0f493b9181c7820c8134437eb8b0b4792085d37dbb24da050476ccb664e59c", size = 4268551, upload-time = "2026-04-08T01:56:46.071Z" }, + { url = "https://files.pythonhosted.org/packages/03/11/5e395f961d6868269835dee1bafec6a1ac176505a167f68b7d8818431068/cryptography-46.0.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ebd6daf519b9f189f85c479427bbd6e9c9037862cf8fe89ee35503bd209ed902", size = 4408887, upload-time = "2026-04-08T01:56:47.718Z" }, + { url = "https://files.pythonhosted.org/packages/40/53/8ed1cf4c3b9c8e611e7122fb56f1c32d09e1fff0f1d77e78d9ff7c82653e/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:b7b412817be92117ec5ed95f880defe9cf18a832e8cafacf0a22337dc1981b4d", size = 4271354, upload-time = "2026-04-08T01:56:49.312Z" }, + { url = "https://files.pythonhosted.org/packages/50/46/cf71e26025c2e767c5609162c866a78e8a2915bbcfa408b7ca495c6140c4/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:fbfd0e5f273877695cb93baf14b185f4878128b250cc9f8e617ea0c025dfb022", size = 4905845, upload-time = "2026-04-08T01:56:50.916Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ea/01276740375bac6249d0a971ebdf6b4dc9ead0ee0a34ef3b5a88c1a9b0d4/cryptography-46.0.7-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:ffca7aa1d00cf7d6469b988c581598f2259e46215e0140af408966a24cf086ce", size = 4444641, upload-time = "2026-04-08T01:56:52.882Z" }, + { url = "https://files.pythonhosted.org/packages/3d/4c/7d258f169ae71230f25d9f3d06caabcff8c3baf0978e2b7d65e0acac3827/cryptography-46.0.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:60627cf07e0d9274338521205899337c5d18249db56865f943cbe753aa96f40f", size = 3967749, upload-time = "2026-04-08T01:56:54.597Z" }, + { url = "https://files.pythonhosted.org/packages/b5/2a/2ea0767cad19e71b3530e4cad9605d0b5e338b6a1e72c37c9c1ceb86c333/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:80406c3065e2c55d7f49a9550fe0c49b3f12e5bfff5dedb727e319e1afb9bf99", size = 4270942, upload-time = "2026-04-08T01:56:56.416Z" }, + { url = "https://files.pythonhosted.org/packages/41/3d/fe14df95a83319af25717677e956567a105bb6ab25641acaa093db79975d/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:c5b1ccd1239f48b7151a65bc6dd54bcfcc15e028c8ac126d3fada09db0e07ef1", size = 4871079, upload-time = "2026-04-08T01:56:58.31Z" }, + { url = "https://files.pythonhosted.org/packages/9c/59/4a479e0f36f8f378d397f4eab4c850b4ffb79a2f0d58704b8fa0703ddc11/cryptography-46.0.7-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d5f7520159cd9c2154eb61eb67548ca05c5774d39e9c2c4339fd793fe7d097b2", size = 4443999, upload-time = "2026-04-08T01:57:00.508Z" }, + { url = "https://files.pythonhosted.org/packages/28/17/b59a741645822ec6d04732b43c5d35e4ef58be7bfa84a81e5ae6f05a1d33/cryptography-46.0.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fcd8eac50d9138c1d7fc53a653ba60a2bee81a505f9f8850b6b2888555a45d0e", size = 4399191, upload-time = "2026-04-08T01:57:02.654Z" }, + { url = "https://files.pythonhosted.org/packages/59/6a/bb2e166d6d0e0955f1e9ff70f10ec4b2824c9cfcdb4da772c7dd69cc7d80/cryptography-46.0.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:65814c60f8cc400c63131584e3e1fad01235edba2614b61fbfbfa954082db0ee", size = 4655782, upload-time = "2026-04-08T01:57:04.592Z" }, + { url = "https://files.pythonhosted.org/packages/95/b6/3da51d48415bcb63b00dc17c2eff3a651b7c4fed484308d0f19b30e8cb2c/cryptography-46.0.7-cp314-cp314t-win32.whl", hash = "sha256:fdd1736fed309b4300346f88f74cd120c27c56852c3838cab416e7a166f67298", size = 3002227, upload-time = "2026-04-08T01:57:06.91Z" }, + { url = "https://files.pythonhosted.org/packages/32/a8/9f0e4ed57ec9cebe506e58db11ae472972ecb0c659e4d52bbaee80ca340a/cryptography-46.0.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e06acf3c99be55aa3b516397fe42f5855597f430add9c17fa46bf2e0fb34c9bb", size = 3475332, upload-time = "2026-04-08T01:57:08.807Z" }, + { url = "https://files.pythonhosted.org/packages/a7/7f/cd42fc3614386bc0c12f0cb3c4ae1fc2bbca5c9662dfed031514911d513d/cryptography-46.0.7-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:462ad5cb1c148a22b2e3bcc5ad52504dff325d17daf5df8d88c17dda1f75f2a4", size = 7165618, upload-time = "2026-04-08T01:57:10.645Z" }, + { url = "https://files.pythonhosted.org/packages/a5/d0/36a49f0262d2319139d2829f773f1b97ef8aef7f97e6e5bd21455e5a8fb5/cryptography-46.0.7-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:84d4cced91f0f159a7ddacad249cc077e63195c36aac40b4150e7a57e84fffe7", size = 4270628, upload-time = "2026-04-08T01:57:12.885Z" }, + { url = "https://files.pythonhosted.org/packages/8a/6c/1a42450f464dda6ffbe578a911f773e54dd48c10f9895a23a7e88b3e7db5/cryptography-46.0.7-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:128c5edfe5e5938b86b03941e94fac9ee793a94452ad1365c9fc3f4f62216832", size = 4415405, upload-time = "2026-04-08T01:57:14.923Z" }, + { url = "https://files.pythonhosted.org/packages/9a/92/4ed714dbe93a066dc1f4b4581a464d2d7dbec9046f7c8b7016f5286329e2/cryptography-46.0.7-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5e51be372b26ef4ba3de3c167cd3d1022934bc838ae9eaad7e644986d2a3d163", size = 4272715, upload-time = "2026-04-08T01:57:16.638Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e6/a26b84096eddd51494bba19111f8fffe976f6a09f132706f8f1bf03f51f7/cryptography-46.0.7-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:cdf1a610ef82abb396451862739e3fc93b071c844399e15b90726ef7470eeaf2", size = 4918400, upload-time = "2026-04-08T01:57:19.021Z" }, + { url = "https://files.pythonhosted.org/packages/c7/08/ffd537b605568a148543ac3c2b239708ae0bd635064bab41359252ef88ed/cryptography-46.0.7-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1d25aee46d0c6f1a501adcddb2d2fee4b979381346a78558ed13e50aa8a59067", size = 4450634, upload-time = "2026-04-08T01:57:21.185Z" }, + { url = "https://files.pythonhosted.org/packages/16/01/0cd51dd86ab5b9befe0d031e276510491976c3a80e9f6e31810cce46c4ad/cryptography-46.0.7-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:cdfbe22376065ffcf8be74dc9a909f032df19bc58a699456a21712d6e5eabfd0", size = 3985233, upload-time = "2026-04-08T01:57:22.862Z" }, + { url = "https://files.pythonhosted.org/packages/92/49/819d6ed3a7d9349c2939f81b500a738cb733ab62fbecdbc1e38e83d45e12/cryptography-46.0.7-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:abad9dac36cbf55de6eb49badd4016806b3165d396f64925bf2999bcb67837ba", size = 4271955, upload-time = "2026-04-08T01:57:24.814Z" }, + { url = "https://files.pythonhosted.org/packages/80/07/ad9b3c56ebb95ed2473d46df0847357e01583f4c52a85754d1a55e29e4d0/cryptography-46.0.7-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:935ce7e3cfdb53e3536119a542b839bb94ec1ad081013e9ab9b7cfd478b05006", size = 4879888, upload-time = "2026-04-08T01:57:26.88Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c7/201d3d58f30c4c2bdbe9b03844c291feb77c20511cc3586daf7edc12a47b/cryptography-46.0.7-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:35719dc79d4730d30f1c2b6474bd6acda36ae2dfae1e3c16f2051f215df33ce0", size = 4449961, upload-time = "2026-04-08T01:57:29.068Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ef/649750cbf96f3033c3c976e112265c33906f8e462291a33d77f90356548c/cryptography-46.0.7-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7bbc6ccf49d05ac8f7d7b5e2e2c33830d4fe2061def88210a126d130d7f71a85", size = 4401696, upload-time = "2026-04-08T01:57:31.029Z" }, + { url = "https://files.pythonhosted.org/packages/41/52/a8908dcb1a389a459a29008c29966c1d552588d4ae6d43f3a1a4512e0ebe/cryptography-46.0.7-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a1529d614f44b863a7b480c6d000fe93b59acee9c82ffa027cfadc77521a9f5e", size = 4664256, upload-time = "2026-04-08T01:57:33.144Z" }, + { url = "https://files.pythonhosted.org/packages/4b/fa/f0ab06238e899cc3fb332623f337a7364f36f4bb3f2534c2bb95a35b132c/cryptography-46.0.7-cp38-abi3-win32.whl", hash = "sha256:f247c8c1a1fb45e12586afbb436ef21ff1e80670b2861a90353d9b025583d246", size = 3013001, upload-time = "2026-04-08T01:57:34.933Z" }, + { url = "https://files.pythonhosted.org/packages/d2/f1/00ce3bde3ca542d1acd8f8cfa38e446840945aa6363f9b74746394b14127/cryptography-46.0.7-cp38-abi3-win_amd64.whl", hash = "sha256:506c4ff91eff4f82bdac7633318a526b1d1309fc07ca76a3ad182cb5b686d6d3", size = 3472985, upload-time = "2026-04-08T01:57:36.714Z" }, + { url = "https://files.pythonhosted.org/packages/63/0c/dca8abb64e7ca4f6b2978769f6fea5ad06686a190cec381f0a796fdcaaba/cryptography-46.0.7-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fc9ab8856ae6cf7c9358430e49b368f3108f050031442eaeb6b9d87e4dcf4e4f", size = 3476879, upload-time = "2026-04-08T01:57:38.664Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ea/075aac6a84b7c271578d81a2f9968acb6e273002408729f2ddff517fed4a/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d3b99c535a9de0adced13d159c5a9cf65c325601aa30f4be08afd680643e9c15", size = 4219700, upload-time = "2026-04-08T01:57:40.625Z" }, + { url = "https://files.pythonhosted.org/packages/6c/7b/1c55db7242b5e5612b29fc7a630e91ee7a6e3c8e7bf5406d22e206875fbd/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d02c738dacda7dc2a74d1b2b3177042009d5cab7c7079db74afc19e56ca1b455", size = 4385982, upload-time = "2026-04-08T01:57:42.725Z" }, + { url = "https://files.pythonhosted.org/packages/cb/da/9870eec4b69c63ef5925bf7d8342b7e13bc2ee3d47791461c4e49ca212f4/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:04959522f938493042d595a736e7dbdff6eb6cc2339c11465b3ff89343b65f65", size = 4219115, upload-time = "2026-04-08T01:57:44.939Z" }, + { url = "https://files.pythonhosted.org/packages/f4/72/05aa5832b82dd341969e9a734d1812a6aadb088d9eb6f0430fc337cc5a8f/cryptography-46.0.7-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:3986ac1dee6def53797289999eabe84798ad7817f3e97779b5061a95b0ee4968", size = 4385479, upload-time = "2026-04-08T01:57:46.86Z" }, + { url = "https://files.pythonhosted.org/packages/20/2a/1b016902351a523aa2bd446b50a5bc1175d7a7d1cf90fe2ef904f9b84ebc/cryptography-46.0.7-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:258514877e15963bd43b558917bc9f54cf7cf866c38aa576ebf47a77ddbc43a4", size = 3412829, upload-time = "2026-04-08T01:57:48.874Z" }, ] [[package]] From 9653034b8d459607a4b7f761e6c23a6f287fa5fa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Apr 2026 12:43:51 +0000 Subject: [PATCH 57/69] =?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 6e2d12980f..3c36aaf0eb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump cryptography from 46.0.5 to 46.0.7. PR [#15314](https://github.com/fastapi/fastapi/pull/15314) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump strawberry-graphql from 0.307.1 to 0.312.3. PR [#15309](https://github.com/fastapi/fastapi/pull/15309) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔨 Add pre-commit hook to ensure latest release header has date. PR [#15293](https://github.com/fastapi/fastapi/pull/15293) by [@YuriiMotov](https://github.com/YuriiMotov). From ae4e45c5cc20a1e1503fbcab2369821d188feb09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 16 Apr 2026 13:35:06 +0200 Subject: [PATCH 58/69] =?UTF-8?q?=F0=9F=94=A5=20Remove=20April=20Fool's=20?= =?UTF-8?q?`@app.vibe()`=20=F0=9F=A4=AA=20(#15363)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/advanced/vibe.md | 44 ---------------------- docs/en/mkdocs.yml | 1 - docs_src/vibe/tutorial001_py310.py | 12 ------ fastapi/applications.py | 60 +----------------------------- tests/test_vibe.py | 17 --------- 5 files changed, 1 insertion(+), 133 deletions(-) delete mode 100644 docs/en/docs/advanced/vibe.md delete mode 100644 docs_src/vibe/tutorial001_py310.py delete mode 100644 tests/test_vibe.py diff --git a/docs/en/docs/advanced/vibe.md b/docs/en/docs/advanced/vibe.md deleted file mode 100644 index 766f3855b7..0000000000 --- a/docs/en/docs/advanced/vibe.md +++ /dev/null @@ -1,44 +0,0 @@ -# Vibe Coding { #vibe-coding } - -Are you tired of all that **data validation**, **documentation**, **serialization**, and all that **boring** stuff? - -Do you just want to **vibe**? 🎶 - -**FastAPI** now supports a new `@app.vibe()` decorator that embraces **modern AI coding best practices**. 🤖 - -## How It Works { #how-it-works } - -The `@app.vibe()` decorator is intended to receive **any HTTP method** (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`, etc.) and **any payload**. - -The body should be annotated with `Any`, because the request and the response would be... well... **anything**. 🤷 - -The idea is that you would receive the payload and send it **directly** to an LLM provider, using a `prompt` to tell the LLM what to do, and return the response **as is**. No questions asked. - -You don't even need to write the body of the function. The `@app.vibe()` decorator does everything for you based on AI vibes: - -{* ../../docs_src/vibe/tutorial001_py310.py hl[8:12] *} - -## Benefits { #benefits } - -By using `@app.vibe()`, you get to enjoy: - -* **Freedom**: No data validation. No schemas. No constraints. Just vibes. ✨ -* **Flexibility**: The request can be anything. The response can be anything. Who needs types anyway? -* **No documentation**: Why document your API when an LLM can figure it out? Auto-generated OpenAPI docs are *so* 2020. -* **No serialization**: Just pass the raw, unstructured data around. Serialization is for people who don't trust their LLMs. -* **Embrace modern AI coding practices**: Leave everything up to an LLM to decide. The model knows best. Always. -* **No code reviews**: There's no code to review. No PRs to approve. No comments to address. Embrace vibe coding fully, replace the theater of approving and merging vibe coded PRs that no one looks at with full proper vibes only. - -/// tip - -This is the ultimate **vibe-driven development** experience. You don't need to think about what your API does, just let the LLM handle it. 🧘 - -/// - -## Try It { #try-it } - -Go ahead, try it: - -{* ../../docs_src/vibe/tutorial001_py310.py *} - -...and see what happens. 😎 diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index a84934f44c..4614194981 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -197,7 +197,6 @@ nav: - advanced/advanced-python-types.md - advanced/json-base64-bytes.md - advanced/strict-content-type.md - - advanced/vibe.md - fastapi-cli.md - editor-support.md - Deployment: diff --git a/docs_src/vibe/tutorial001_py310.py b/docs_src/vibe/tutorial001_py310.py deleted file mode 100644 index 4ec3d55552..0000000000 --- a/docs_src/vibe/tutorial001_py310.py +++ /dev/null @@ -1,12 +0,0 @@ -from typing import Any - -from fastapi import FastAPI - -app = FastAPI() - - -@app.vibe( - "/vibe/", - prompt="pls return json of users from database. make no mistakes", -) -async def ai_vibes(body: Any): ... diff --git a/fastapi/applications.py b/fastapi/applications.py index dfd80d4b1f..4af1146b0d 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -10,11 +10,7 @@ from fastapi.exception_handlers import ( request_validation_exception_handler, websocket_request_validation_exception_handler, ) -from fastapi.exceptions import ( - FastAPIError, - RequestValidationError, - WebSocketRequestValidationError, -) +from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError from fastapi.logger import logger from fastapi.middleware.asyncexitstack import AsyncExitStackMiddleware from fastapi.openapi.docs import ( @@ -4563,60 +4559,6 @@ class FastAPI(Starlette): generate_unique_id_function=generate_unique_id_function, ) - def vibe( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/vibes`, the path is `/vibes`. - """ - ), - ], - *, - prompt: Annotated[ - str, - Doc( - """ - The prompt to send to the LLM provider along with the payload. - - This tells the LLM what to do with the request body. - """ - ), - ] = "", - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *vibe coding path operation* that receives any HTTP method - and any payload. - - It's intended to receive the request and send the payload directly - to an LLM provider, and return the response as is. - - Embrace the freedom and flexibility of not having any data validation, - documentation, or serialization. - - ## Example - - ```python - from typing import Any - - from fastapi import FastAPI - - app = FastAPI() - - - @app.vibe( - "/vibe/", - prompt="pls return json of users from database. make no mistakes", - ) - async def ai_vibes(body: Any): - ... - ``` - """ - raise FastAPIError("Are you kidding me? Happy April Fool's") - def websocket_route( self, path: str, name: str | None = None ) -> Callable[[DecoratedCallable], DecoratedCallable]: diff --git a/tests/test_vibe.py b/tests/test_vibe.py deleted file mode 100644 index 4a79d6b6cd..0000000000 --- a/tests/test_vibe.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Any - -import pytest -from fastapi import FastAPI -from fastapi.exceptions import FastAPIError - - -def test_vibe_raises(): - with pytest.raises(FastAPIError, match="Are you kidding me"): - app = FastAPI() - - @app.vibe( - "/vibe/", - prompt="pls return json of users from database. make no mistakes", - ) - async def ai_vibes(body: Any): # pragma: nocover - pass From 09d1d1cb7073b3c7bd1f58fcf6faefa9b2c29de4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 Apr 2026 11:35:32 +0000 Subject: [PATCH 59/69] =?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 3c36aaf0eb..8ebff9e059 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Refactors + +* 🔥 Remove April Fool's `@app.vibe()` 🤪. PR [#15363](https://github.com/fastapi/fastapi/pull/15363) by [@tiangolo](https://github.com/tiangolo). + ### Internal * ⬆ Bump cryptography from 46.0.5 to 46.0.7. PR [#15314](https://github.com/fastapi/fastapi/pull/15314) by [@dependabot[bot]](https://github.com/apps/dependabot). From f796c346a8537876de43729ff1ca1409d4648893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 16 Apr 2026 13:37:43 +0200 Subject: [PATCH 60/69] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.135.?= =?UTF-8?q?4?= 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 8ebff9e059..f2d6af7a76 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.135.4 (2026-04-16) + ### Refactors * 🔥 Remove April Fool's `@app.vibe()` 🤪. PR [#15363](https://github.com/fastapi/fastapi/pull/15363) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 31bc87c18c..21cf17498d 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.135.3" +__version__ = "0.135.4" from starlette import status as status From 4b264878d71b2dc0e9e0f90ef15459d4302a7f9c Mon Sep 17 00:00:00 2001 From: Sofie Van Landeghem Date: Thu, 16 Apr 2026 13:42:00 +0200 Subject: [PATCH 61/69] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Support=20free-threa?= =?UTF-8?q?ded=20Python=203.14t=20(#15149)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 25 +- fastapi/responses.py | 27 +- pyproject.toml | 7 +- tests/test_default_response_class.py | 8 +- tests/test_deprecated_responses.py | 6 + tests/test_orjson_response_class.py | 4 + .../test_custom_response/test_tutorial001.py | 2 + .../test_custom_response/test_tutorial001b.py | 2 + .../test_custom_response/test_tutorial009c.py | 3 + tests/utils.py | 11 + uv.lock | 437 +++++------------- 11 files changed, 190 insertions(+), 342 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e852e0f25d..ed78f6e53f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,7 +49,8 @@ jobs: strategy: matrix: os: [ windows-latest, macos-latest ] - python-version: [ "3.14" ] + python-version: [ "3.14", "3.14t" ] + deprecated-tests: [ "no-deprecation" ] uv-resolution: - highest starlette-src: @@ -60,23 +61,33 @@ jobs: python-version: "3.10" coverage: coverage uv-resolution: lowest-direct + deprecated-tests: "no-deprecation" - os: windows-latest python-version: "3.12" coverage: coverage uv-resolution: lowest-direct + deprecated-tests: "no-deprecation" - os: ubuntu-latest python-version: "3.13" coverage: coverage uv-resolution: highest + deprecated-tests: "no-deprecation" - os: ubuntu-latest python-version: "3.13" uv-resolution: highest codspeed: codspeed + deprecated-tests: "no-deprecation" - os: ubuntu-latest python-version: "3.14" coverage: coverage uv-resolution: highest starlette-src: starlette-git + deprecated-tests: "test-deprecation" + - os: ubuntu-latest + python-version: "3.14t" + coverage: coverage + uv-resolution: highest + deprecated-tests: "no-deprecation" fail-fast: false runs-on: ${{ matrix.os }} env: @@ -108,18 +119,24 @@ jobs: - name: Install Starlette from source if: matrix.starlette-src == 'starlette-git' run: uv pip install "git+https://github.com/Kludex/starlette@main" + - name: Install deprecated libraries just for testing + if: matrix.deprecated-tests == 'test-deprecation' + run: uv pip install orjson ujson + - name: Reinstall SQLAlchemy without Cython extensions + if: matrix.python-version == '3.14t' && matrix.os == 'ubuntu-latest' + run: "DISABLE_SQLALCHEMY_CEXT=1 uv pip install --force-reinstall --no-binary :all: sqlalchemy" - run: mkdir coverage - name: Test run: uv run --no-sync bash scripts/test-cov.sh env: - COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }} - CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }} + COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-${{ matrix.deprecated-tests}} + CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}-${{ matrix.deprecated-tests}} # Do not store coverage for all possible combinations to avoid file size max errors in Smokeshow - name: Store coverage files if: matrix.coverage == 'coverage' uses: actions/upload-artifact@v7 with: - name: coverage-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/coverage/.coverage.*') }} + name: coverage-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.deprecated-tests}}-${{ hashFiles('**/coverage/.coverage.*') }} path: coverage include-hidden-files: true diff --git a/fastapi/responses.py b/fastapi/responses.py index 554b0952b0..970f365513 100644 --- a/fastapi/responses.py +++ b/fastapi/responses.py @@ -1,4 +1,5 @@ -from typing import Any +import importlib +from typing import Any, Protocol, cast from fastapi.exceptions import FastAPIDeprecationWarning from fastapi.sse import EventSourceResponse as EventSourceResponse # noqa @@ -11,16 +12,28 @@ from starlette.responses import Response as Response # noqa from starlette.responses import StreamingResponse as StreamingResponse # noqa from typing_extensions import deprecated + +class _UjsonModule(Protocol): + def dumps(self, __obj: Any, *, ensure_ascii: bool = ...) -> str: ... + + +class _OrjsonModule(Protocol): + OPT_NON_STR_KEYS: int + OPT_SERIALIZE_NUMPY: int + + def dumps(self, __obj: Any, *, option: int = ...) -> bytes: ... + + try: - import ujson -except ImportError: # pragma: nocover - ujson = None # type: ignore + ujson = cast(_UjsonModule, importlib.import_module("ujson")) +except ModuleNotFoundError: # pragma: nocover + ujson = None # type: ignore # ty: ignore[unused-ignore-comment] try: - import orjson -except ImportError: # pragma: nocover - orjson = None # type: ignore + orjson = cast(_OrjsonModule, importlib.import_module("orjson")) +except ModuleNotFoundError: # pragma: nocover + orjson = None # type: ignore # ty: ignore[unused-ignore-comment] @deprecated( diff --git a/pyproject.toml b/pyproject.toml index 612d8a0d8a..60530b6370 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,6 +59,7 @@ Changelog = "https://fastapi.tiangolo.com/release-notes/" [project.optional-dependencies] standard = [ "fastapi-cli[standard] >=0.0.8", + "fastar >= 0.9.0", # For the test client "httpx >=0.23.0,<1.0.0", # For templates @@ -149,10 +150,6 @@ docs = [ docs-tests = [ "httpx >=0.23.0,<1.0.0", "ruff >=0.14.14", - # For UJSONResponse - "ujson >=5.8.0", - # For ORJSONResponse - "orjson >=3.9.3", ] github-actions = [ "httpx >=0.27.0,<1.0.0", @@ -178,8 +175,6 @@ tests = [ "sqlmodel >=0.0.31", "strawberry-graphql >=0.200.0,<1.0.0", "ty>=0.0.9", - "types-orjson >=3.6.2", - "types-ujson >=5.10.0.20240515", "a2wsgi >=1.9.0,<=2.0.0", "pytest-xdist[psutil]>=2.5.0", "pytest-cov>=4.0.0", diff --git a/tests/test_default_response_class.py b/tests/test_default_response_class.py index 042fb1dea9..88498e5601 100644 --- a/tests/test_default_response_class.py +++ b/tests/test_default_response_class.py @@ -1,15 +1,18 @@ from typing import Any -import orjson from fastapi import APIRouter, FastAPI from fastapi.responses import HTMLResponse, JSONResponse, PlainTextResponse from fastapi.testclient import TestClient +from tests.utils import needs_orjson + class ORJSONResponse(JSONResponse): media_type = "application/x-orjson" def render(self, content: Any) -> bytes: + import orjson + return orjson.dumps(content) @@ -118,6 +121,7 @@ html_type = "text/html; charset=utf-8" override_type = "application/x-override" +@needs_orjson def test_app(): with client: response = client.get("/") @@ -132,6 +136,7 @@ def test_app_override(): assert response.headers["content-type"] == text_type +@needs_orjson def test_router_a(): with client: response = client.get("/a") @@ -146,6 +151,7 @@ def test_router_a_override(): assert response.headers["content-type"] == text_type +@needs_orjson def test_router_a_a(): with client: response = client.get("/a/a") diff --git a/tests/test_deprecated_responses.py b/tests/test_deprecated_responses.py index eff5792717..8cbd9c11fe 100644 --- a/tests/test_deprecated_responses.py +++ b/tests/test_deprecated_responses.py @@ -7,6 +7,8 @@ from fastapi.responses import ORJSONResponse, UJSONResponse from fastapi.testclient import TestClient from pydantic import BaseModel +from tests.utils import needs_orjson, needs_ujson + class Item(BaseModel): name: str @@ -28,6 +30,7 @@ def _make_orjson_app() -> FastAPI: return app +@needs_orjson def test_orjson_response_returns_correct_data(): app = _make_orjson_app() client = TestClient(app) @@ -38,6 +41,7 @@ def test_orjson_response_returns_correct_data(): assert response.json() == {"name": "widget", "price": 9.99} +@needs_orjson def test_orjson_response_emits_deprecation_warning(): with pytest.warns(FastAPIDeprecationWarning, match="ORJSONResponse is deprecated"): ORJSONResponse(content={"hello": "world"}) @@ -58,6 +62,7 @@ def _make_ujson_app() -> FastAPI: return app +@needs_ujson def test_ujson_response_returns_correct_data(): app = _make_ujson_app() client = TestClient(app) @@ -68,6 +73,7 @@ def test_ujson_response_returns_correct_data(): assert response.json() == {"name": "widget", "price": 9.99} +@needs_ujson def test_ujson_response_emits_deprecation_warning(): with pytest.warns(FastAPIDeprecationWarning, match="UJSONResponse is deprecated"): UJSONResponse(content={"hello": "world"}) diff --git a/tests/test_orjson_response_class.py b/tests/test_orjson_response_class.py index 63ea054d1f..3e34041dc9 100644 --- a/tests/test_orjson_response_class.py +++ b/tests/test_orjson_response_class.py @@ -1,5 +1,9 @@ import warnings +import pytest + +pytest.importorskip("orjson") + from fastapi import FastAPI from fastapi.exceptions import FastAPIDeprecationWarning from fastapi.responses import ORJSONResponse diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001.py b/tests/test_tutorial/test_custom_response/test_tutorial001.py index a691dd3a84..42e4158f56 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial001.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial001.py @@ -4,6 +4,8 @@ import pytest from fastapi.testclient import TestClient from inline_snapshot import snapshot +pytest.importorskip("orjson") + @pytest.fixture( name="client", diff --git a/tests/test_tutorial/test_custom_response/test_tutorial001b.py b/tests/test_tutorial/test_custom_response/test_tutorial001b.py index 11ce813b76..f783e563cb 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial001b.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial001b.py @@ -11,6 +11,8 @@ with warnings.catch_warnings(): client = TestClient(app) +pytest.importorskip("orjson") + @pytest.mark.filterwarnings("ignore::fastapi.exceptions.FastAPIDeprecationWarning") def test_get_custom_response(): diff --git a/tests/test_tutorial/test_custom_response/test_tutorial009c.py b/tests/test_tutorial/test_custom_response/test_tutorial009c.py index 7a1b713079..bc41ca0c25 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial009c.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial009c.py @@ -1,5 +1,8 @@ +import pytest from fastapi.testclient import TestClient +pytest.importorskip("orjson") + from docs_src.custom_response.tutorial009c_py310 import app client = TestClient(app) diff --git a/tests/utils.py b/tests/utils.py index fff7348b9c..934d3b0fa4 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,3 +1,4 @@ +import importlib import sys import pytest @@ -9,6 +10,16 @@ needs_py314 = pytest.mark.skipif( sys.version_info < (3, 14), reason="requires python3.14+" ) +needs_orjson = pytest.mark.skipif( + importlib.util.find_spec("orjson") is None, + reason="requires orjson", +) + +needs_ujson = pytest.mark.skipif( + importlib.util.find_spec("ujson") is None, + reason="requires ujson", +) + workdir_lock = pytest.mark.xdist_group("workdir_lock") diff --git a/uv.lock b/uv.lock index 7f27dbc7f4..a47632d5a0 100644 --- a/uv.lock +++ b/uv.lock @@ -1092,6 +1092,7 @@ all = [ standard = [ { name = "email-validator" }, { name = "fastapi-cli", extra = ["standard"] }, + { name = "fastar" }, { name = "httpx" }, { name = "jinja2" }, { name = "pydantic-extra-types" }, @@ -1133,7 +1134,6 @@ dev = [ { name = "mkdocs-redirects" }, { name = "mkdocstrings", extra = ["python"] }, { name = "mypy" }, - { name = "orjson" }, { name = "pillow" }, { name = "playwright" }, { name = "prek" }, @@ -1154,9 +1154,6 @@ dev = [ { name = "strawberry-graphql" }, { name = "ty" }, { name = "typer" }, - { name = "types-orjson" }, - { name = "types-ujson" }, - { name = "ujson" }, ] docs = [ { name = "black" }, @@ -1172,19 +1169,15 @@ docs = [ { name = "mkdocs-material" }, { name = "mkdocs-redirects" }, { name = "mkdocstrings", extra = ["python"] }, - { name = "orjson" }, { name = "pillow" }, { name = "python-slugify" }, { name = "pyyaml" }, { name = "ruff" }, { name = "typer" }, - { name = "ujson" }, ] docs-tests = [ { name = "httpx" }, - { name = "orjson" }, { name = "ruff" }, - { name = "ujson" }, ] github-actions = [ { name = "httpx" }, @@ -1203,7 +1196,6 @@ tests = [ { name = "httpx" }, { name = "inline-snapshot" }, { name = "mypy" }, - { name = "orjson" }, { name = "pwdlib", extra = ["argon2"] }, { name = "pyjwt" }, { name = "pytest" }, @@ -1217,9 +1209,6 @@ tests = [ { name = "sqlmodel" }, { name = "strawberry-graphql" }, { name = "ty" }, - { name = "types-orjson" }, - { name = "types-ujson" }, - { name = "ujson" }, ] translations = [ { name = "gitpython" }, @@ -1236,6 +1225,7 @@ requires-dist = [ { name = "fastapi-cli", extras = ["standard"], marker = "extra == 'all'", specifier = ">=0.0.8" }, { name = "fastapi-cli", extras = ["standard"], marker = "extra == 'standard'", specifier = ">=0.0.8" }, { name = "fastapi-cli", extras = ["standard-no-fastapi-cloud-cli"], marker = "extra == 'standard-no-fastapi-cloud-cli'", specifier = ">=0.0.8" }, + { name = "fastar", marker = "extra == 'standard'", specifier = ">=0.9.0" }, { name = "httpx", marker = "extra == 'all'", specifier = ">=0.23.0,<1.0.0" }, { name = "httpx", marker = "extra == 'standard'", specifier = ">=0.23.0,<1.0.0" }, { name = "httpx", marker = "extra == 'standard-no-fastapi-cloud-cli'", specifier = ">=0.23.0,<1.0.0" }, @@ -1286,7 +1276,6 @@ dev = [ { name = "mkdocs-redirects", specifier = ">=1.2.1,<1.3.0" }, { name = "mkdocstrings", extras = ["python"], specifier = ">=0.30.1" }, { name = "mypy", specifier = ">=1.14.1" }, - { name = "orjson", specifier = ">=3.9.3" }, { name = "pillow", specifier = ">=11.3.0" }, { name = "playwright", specifier = ">=1.57.0" }, { name = "prek", specifier = ">=0.2.22" }, @@ -1307,9 +1296,6 @@ dev = [ { name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" }, { name = "ty", specifier = ">=0.0.9" }, { name = "typer", specifier = ">=0.21.1" }, - { name = "types-orjson", specifier = ">=3.6.2" }, - { name = "types-ujson", specifier = ">=5.10.0.20240515" }, - { name = "ujson", specifier = ">=5.8.0" }, ] docs = [ { name = "black", specifier = ">=25.1.0" }, @@ -1325,19 +1311,15 @@ docs = [ { name = "mkdocs-material", specifier = ">=9.7.0" }, { name = "mkdocs-redirects", specifier = ">=1.2.1,<1.3.0" }, { name = "mkdocstrings", extras = ["python"], specifier = ">=0.30.1" }, - { name = "orjson", specifier = ">=3.9.3" }, { name = "pillow", specifier = ">=11.3.0" }, { name = "python-slugify", specifier = ">=8.0.4" }, { name = "pyyaml", specifier = ">=5.3.1,<7.0.0" }, { name = "ruff", specifier = ">=0.14.14" }, { name = "typer", specifier = ">=0.21.1" }, - { name = "ujson", specifier = ">=5.8.0" }, ] docs-tests = [ { name = "httpx", specifier = ">=0.23.0,<1.0.0" }, - { name = "orjson", specifier = ">=3.9.3" }, { name = "ruff", specifier = ">=0.14.14" }, - { name = "ujson", specifier = ">=5.8.0" }, ] github-actions = [ { name = "httpx", specifier = ">=0.27.0,<1.0.0" }, @@ -1356,7 +1338,6 @@ tests = [ { name = "httpx", specifier = ">=0.23.0,<1.0.0" }, { name = "inline-snapshot", specifier = ">=0.21.1" }, { name = "mypy", specifier = ">=1.14.1" }, - { name = "orjson", specifier = ">=3.9.3" }, { name = "pwdlib", extras = ["argon2"], specifier = ">=0.2.1" }, { name = "pyjwt", specifier = ">=2.9.0" }, { name = "pytest", specifier = ">=9.0.0" }, @@ -1370,9 +1351,6 @@ tests = [ { name = "sqlmodel", specifier = ">=0.0.31" }, { name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" }, { name = "ty", specifier = ">=0.0.9" }, - { name = "types-orjson", specifier = ">=3.6.2" }, - { name = "types-ujson", specifier = ">=5.10.0.20240515" }, - { name = "ujson", specifier = ">=5.8.0" }, ] translations = [ { name = "gitpython", specifier = ">=3.1.46" }, @@ -1425,123 +1403,118 @@ wheels = [ [[package]] name = "fastar" -version = "0.8.0" +version = "0.9.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/69/e7/f89d54fb04104114dd0552836dc2b47914f416cc0e200b409dd04a33de5e/fastar-0.8.0.tar.gz", hash = "sha256:f4d4d68dbf1c4c2808f0e730fac5843493fc849f70fe3ad3af60dfbaf68b9a12", size = 68524, upload-time = "2025-11-26T02:36:00.72Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c3/e2/51d9ee443aabcd5aa581d45b18b6198ced364b5cd97e5504c5d782ceb82c/fastar-0.8.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c9f930cff014cf79d396d0541bd9f3a3f170c9b5e45d10d634d98f9ed08788c3", size = 708536, upload-time = "2025-11-26T02:34:35.236Z" }, - { url = "https://files.pythonhosted.org/packages/07/2a/edfc6274768b8a3859a5ca4f8c29cb7f614d7f27d2378e2c88aa91cda54e/fastar-0.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07b70f712d20622346531a4b46bb332569bea621f61314c0b7e80903a16d14cf", size = 632235, upload-time = "2025-11-26T02:34:19.367Z" }, - { url = "https://files.pythonhosted.org/packages/ef/1e/3cfbaaec464caef196700ee2ffae1c03f94f7c5e2a85d0ec0ea9cdd1da81/fastar-0.8.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:330639db3bfba4c6d132421a2a4aeb81e7bea8ce9159cdb6e247fbc5fae97686", size = 871386, upload-time = "2025-11-26T02:33:47.613Z" }, - { url = "https://files.pythonhosted.org/packages/82/50/224a674ad541054179e4e6e0b54bb6e162f04f698a2512b42a8085fc6b6f/fastar-0.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98ea7ceb6231e48d7bb0d7dc13e946baa29c7f6873eaf4afb69725d6da349033", size = 764955, upload-time = "2025-11-26T02:32:44.279Z" }, - { url = "https://files.pythonhosted.org/packages/4d/5e/4608184aa57cb6a54f62c1eb3e5133ba8d461fc7f13193c0255effbec12a/fastar-0.8.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a90695a601a78bbca910fdf2efcdf3103c55d0de5a5c6e93556d707bf886250b", size = 765987, upload-time = "2025-11-26T02:32:59.701Z" }, - { url = "https://files.pythonhosted.org/packages/e0/53/6afd2b680dddfa10df9a16bbcf6cabfee0d92435d5c7e3f4cfe3b1712662/fastar-0.8.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d0bf655ff4c9320b0ca8a5b128063d5093c0c8c1645a2b5f7167143fd8531aa", size = 930900, upload-time = "2025-11-26T02:33:16.059Z" }, - { url = "https://files.pythonhosted.org/packages/ef/1e/b7a304bfcc1d06845cbfa4b464516f6fff9c8c6692f6ef80a3a86b04e199/fastar-0.8.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d8df22cdd8d58e7689aa89b2e4a07e8e5fa4f88d2d9c2621f0e88a49be97ccea", size = 821523, upload-time = "2025-11-26T02:33:30.897Z" }, - { url = "https://files.pythonhosted.org/packages/1d/da/9ef8605c6d233cd6ca3a95f7f518ac22aa064903afe6afa57733bfb7c31b/fastar-0.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8a5e6ad722685128521c8fb44cf25bd38669650ba3a4b466b8903e5aa28e1a0", size = 821268, upload-time = "2025-11-26T02:34:04.003Z" }, - { url = "https://files.pythonhosted.org/packages/7e/22/ed37c78a6b4420de1677d82e79742787975c34847229c33dc376334c7283/fastar-0.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:31cd541231a2456e32104da891cf9962c3b40234d0465cbf9322a6bc8a1b05d5", size = 986286, upload-time = "2025-11-26T02:34:50.279Z" }, - { url = "https://files.pythonhosted.org/packages/ca/a6/366b15f432d85d4089e6e4b52a09cc2a2bcf4d7a1f0771e3d3194deccb1e/fastar-0.8.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:175db2a98d67ced106468e8987975484f8bbbd5ad99201da823b38bafb565ed5", size = 1041921, upload-time = "2025-11-26T02:35:07.292Z" }, - { url = "https://files.pythonhosted.org/packages/f4/45/45f8e6991e3ce9f8aeefdc8d4c200daada41097a36808643d1703464c3e2/fastar-0.8.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ada877ab1c65197d772ce1b1c2e244d4799680d8b3f136a4308360f3d8661b23", size = 1047302, upload-time = "2025-11-26T02:35:24.995Z" }, - { url = "https://files.pythonhosted.org/packages/c2/e2/a587796111a3cd4b78cd61ec3fc1252d8517d81f763f4164ed5680f84810/fastar-0.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:01084cb75f13ca6a8e80bd41584322523189f8e81b472053743d6e6c3062b5a6", size = 995141, upload-time = "2025-11-26T02:35:42.449Z" }, - { url = "https://files.pythonhosted.org/packages/89/c0/7a8ec86695b0b77168e220cf2af1aa30592f5ecdbd0ce6d641d29c4a8bae/fastar-0.8.0-cp310-cp310-win32.whl", hash = "sha256:ca639b9909805e44364ea13cca2682b487e74826e4ad75957115ec693228d6b6", size = 456544, upload-time = "2025-11-26T02:36:23.801Z" }, - { url = "https://files.pythonhosted.org/packages/be/a9/8da4deb840121c59deabd939ce2dca3d6beec85576f3743d1144441938b5/fastar-0.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:fbc0f2ed0f4add7fb58034c576584d44d7eaaf93dee721dfb26dbed6e222dbac", size = 490701, upload-time = "2025-11-26T02:36:09.625Z" }, - { url = "https://files.pythonhosted.org/packages/cd/15/1c764530b81b266f6d27d78d49b6bef22a73b3300cd83a280bfd244908c5/fastar-0.8.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:cd9c0d3ebf7a0a6f642f771cf41b79f7c98d40a3072a8abe1174fbd9bd615bd3", size = 708427, upload-time = "2025-11-26T02:34:36.502Z" }, - { url = "https://files.pythonhosted.org/packages/41/fc/75d42c008516543219e4293e4d8ac55da57a5c63147484f10468bd1bc24e/fastar-0.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2875a077340fe4f8099bd3ed8fa90d9595e1ac3cd62ae19ab690d5bf550eeb35", size = 631740, upload-time = "2025-11-26T02:34:20.718Z" }, - { url = "https://files.pythonhosted.org/packages/50/8d/9632984f7824ed2210157dcebd8e9821ef6d4f2b28510d0516db6625ff9b/fastar-0.8.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a999263d9f87184bf2801833b2ecf105e03c0dd91cac78685673b70da564fd64", size = 871628, upload-time = "2025-11-26T02:33:49.279Z" }, - { url = "https://files.pythonhosted.org/packages/05/97/3eb6ea71b7544d45cd29cacb764ca23cde8ce0aed1a6a02251caa4c0a818/fastar-0.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c41111da56430f638cbfc498ebdcc7d30f63416e904b27b7695c29bd4889cb8", size = 765005, upload-time = "2025-11-26T02:32:45.833Z" }, - { url = "https://files.pythonhosted.org/packages/d6/45/3eb0ee945a0b5d5f9df7e7c25c037ce7fa441cd0b4d44f76d286e2f4396a/fastar-0.8.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3719541a12bb09ab1eae91d2c987a9b2b7d7149c52e7109ba6e15b74aabc49b1", size = 765587, upload-time = "2025-11-26T02:33:01.174Z" }, - { url = "https://files.pythonhosted.org/packages/51/bb/7defd6ec0d9570b1987d8ebde52d07d97f3f26e10b592fb3e12738eba39a/fastar-0.8.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7a9b0fff8079b18acdface7ef1b7f522fd9a589f65ca4a1a0dd7c92a0886c2a2", size = 931150, upload-time = "2025-11-26T02:33:17.374Z" }, - { url = "https://files.pythonhosted.org/packages/28/54/62e51e684dab347c61878afbf09e177029c1a91eb1e39ef244e6b3ef9efa/fastar-0.8.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ac073576c1931959191cb20df38bab21dd152f66c940aa3ca8b22e39f753b2f3", size = 821354, upload-time = "2025-11-26T02:33:32.083Z" }, - { url = "https://files.pythonhosted.org/packages/53/a8/12708ea4d21e3cf9f485b2a67d44ce84d949a6eddcc9aa5b3d324585ab43/fastar-0.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:003b59a7c3e405b6a7bff8fab17d31e0ccbc7f06730a8f8ca1694eeea75f3c76", size = 821626, upload-time = "2025-11-26T02:34:05.685Z" }, - { url = "https://files.pythonhosted.org/packages/e7/c4/1b4d3347c7a759853f963410bf6baf42fe014d587c50c39c8e145f4bf1a0/fastar-0.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a7b96748425efd9fc155cd920d65088a1b0d754421962418ea73413d02ff515a", size = 986187, upload-time = "2025-11-26T02:34:52.047Z" }, - { url = "https://files.pythonhosted.org/packages/dc/59/2dbe0dc2570764475e60030403738faa261a9d3bff16b08629c378ab939a/fastar-0.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:90957a30e64418b02df5b4d525bea50403d98a4b1f29143ce5914ddfa7e54ee4", size = 1041536, upload-time = "2025-11-26T02:35:08.926Z" }, - { url = "https://files.pythonhosted.org/packages/d9/0f/639b295669c7ca6fbc2b4be2a7832aaeac1a5e06923f15a8a6d6daecbc7d/fastar-0.8.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f6e784a8015623fbb7ccca1af372fd82cb511b408ddd2348dc929fc6e415df73", size = 1047149, upload-time = "2025-11-26T02:35:26.597Z" }, - { url = "https://files.pythonhosted.org/packages/cb/e7/23e3a19e06d261d1894f98eca9458f98c090c505a0c712dafc0ff1fc2965/fastar-0.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a03eaf287bbc93064688a1220580ce261e7557c8898f687f4d0b281c85b28d3c", size = 994992, upload-time = "2025-11-26T02:35:44.009Z" }, - { url = "https://files.pythonhosted.org/packages/f2/7a/3ea4726bae3ac9358d02107ae48f3e10ee186dbed554af79e00b7b498c44/fastar-0.8.0-cp311-cp311-win32.whl", hash = "sha256:661a47ed90762f419406c47e802f46af63a08254ba96abd1c8191e4ce967b665", size = 456449, upload-time = "2025-11-26T02:36:25.291Z" }, - { url = "https://files.pythonhosted.org/packages/cb/3c/0142bee993c431ee91cf5535e6e4b079ad491f620c215fcd79b7e5ffeb2b/fastar-0.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:b48abd6056fef7bc3d414aafb453c5b07fdf06d2df5a2841d650288a3aa1e9d3", size = 490863, upload-time = "2025-11-26T02:36:11.114Z" }, - { url = "https://files.pythonhosted.org/packages/3b/18/d119944f6bdbf6e722e204e36db86390ea45684a1bf6be6e3aa42abd471f/fastar-0.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:50c18788b3c6ffb85e176dcb8548bb8e54616a0519dcdbbfba66f6bbc4316933", size = 462230, upload-time = "2025-11-26T02:36:01.917Z" }, - { url = "https://files.pythonhosted.org/packages/58/f1/5b2ff898abac7f1a418284aad285e3a4f68d189c572ab2db0f6c9079dd16/fastar-0.8.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f10d2adfe40f47ff228f4efaa32d409d732ded98580e03ed37c9535b5fc923d", size = 706369, upload-time = "2025-11-26T02:34:37.783Z" }, - { url = "https://files.pythonhosted.org/packages/23/60/8046a386dca39154f80c927cbbeeb4b1c1267a3271bffe61552eb9995757/fastar-0.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b930da9d598e3bc69513d131f397e6d6be4643926ef3de5d33d1e826631eb036", size = 629097, upload-time = "2025-11-26T02:34:21.888Z" }, - { url = "https://files.pythonhosted.org/packages/22/7e/1ae005addc789924a9268da2394d3bb5c6f96836f7e37b7e3d23c2362675/fastar-0.8.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9d210da2de733ca801de83e931012349d209f38b92d9630ccaa94bd445bdc9b8", size = 868938, upload-time = "2025-11-26T02:33:51.119Z" }, - { url = "https://files.pythonhosted.org/packages/a6/77/290a892b073b84bf82e6b2259708dfe79c54f356e252c2dd40180b16fe07/fastar-0.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa02270721517078a5bd61a38719070ac2537a4aa6b6c48cf369cf2abc59174a", size = 765204, upload-time = "2025-11-26T02:32:47.02Z" }, - { url = "https://files.pythonhosted.org/packages/d0/00/c3155171b976003af3281f5258189f1935b15d1221bfc7467b478c631216/fastar-0.8.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:83c391e5b789a720e4d0029b9559f5d6dee3226693c5b39c0eab8eaece997e0f", size = 764717, upload-time = "2025-11-26T02:33:02.453Z" }, - { url = "https://files.pythonhosted.org/packages/b7/43/405b7ad76207b2c11b7b59335b70eac19e4a2653977f5588a1ac8fed54f4/fastar-0.8.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3258d7a78a72793cdd081545da61cabe85b1f37634a1d0b97ffee0ff11d105ef", size = 931502, upload-time = "2025-11-26T02:33:18.619Z" }, - { url = "https://files.pythonhosted.org/packages/da/8a/a3dde6d37cc3da4453f2845cdf16675b5686b73b164f37e2cc579b057c2c/fastar-0.8.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6eab95dd985cdb6a50666cbeb9e4814676e59cfe52039c880b69d67cfd44767", size = 821454, upload-time = "2025-11-26T02:33:33.427Z" }, - { url = "https://files.pythonhosted.org/packages/da/c1/904fe2468609c8990dce9fe654df3fbc7324a8d8e80d8240ae2c89757064/fastar-0.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:829b1854166141860887273c116c94e31357213fa8e9fe8baeb18bd6c38aa8d9", size = 821647, upload-time = "2025-11-26T02:34:07Z" }, - { url = "https://files.pythonhosted.org/packages/c8/73/a0642ab7a400bc07528091785e868ace598fde06fcd139b8f865ec1b6f3c/fastar-0.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b1667eae13f9457a3c737f4376d68e8c3e548353538b28f7e4273a30cb3965cd", size = 986342, upload-time = "2025-11-26T02:34:53.371Z" }, - { url = "https://files.pythonhosted.org/packages/af/af/60c1bfa6edab72366461a95f053d0f5f7ab1825fe65ca2ca367432cd8629/fastar-0.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b864a95229a7db0814cd9ef7987cb713fd43dce1b0d809dd17d9cd6f02fdde3e", size = 1040207, upload-time = "2025-11-26T02:35:10.65Z" }, - { url = "https://files.pythonhosted.org/packages/f6/a0/0d624290dec622e7fa084b6881f456809f68777d54a314f5dde932714506/fastar-0.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c05fbc5618ce17675a42576fa49858d79734627f0a0c74c0875ab45ee8de340c", size = 1045031, upload-time = "2025-11-26T02:35:28.108Z" }, - { url = "https://files.pythonhosted.org/packages/a7/74/cf663af53c4706ba88e6b4af44a6b0c3bd7d7ca09f079dc40647a8f06585/fastar-0.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7f41c51ee96f338662ee3c3df4840511ba3f9969606840f1b10b7cb633a3c716", size = 994877, upload-time = "2025-11-26T02:35:45.797Z" }, - { url = "https://files.pythonhosted.org/packages/52/17/444c8be6e77206050e350da7c338102b6cab384be937fa0b1d6d1f9ede73/fastar-0.8.0-cp312-cp312-win32.whl", hash = "sha256:d949a1a2ea7968b734632c009df0571c94636a5e1622c87a6e2bf712a7334f47", size = 455996, upload-time = "2025-11-26T02:36:26.938Z" }, - { url = "https://files.pythonhosted.org/packages/dc/34/fc3b5e56d71a17b1904800003d9251716e8fd65f662e1b10a26881698a74/fastar-0.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:fc645994d5b927d769121094e8a649b09923b3c13a8b0b98696d8f853f23c532", size = 490429, upload-time = "2025-11-26T02:36:12.707Z" }, - { url = "https://files.pythonhosted.org/packages/35/a8/5608cc837417107c594e2e7be850b9365bcb05e99645966a5d6a156285fe/fastar-0.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:d81ee82e8dc78a0adb81728383bd39611177d642a8fa2d601d4ad5ad59e5f3bd", size = 461297, upload-time = "2025-11-26T02:36:03.546Z" }, - { url = "https://files.pythonhosted.org/packages/d1/a5/79ecba3646e22d03eef1a66fb7fc156567213e2e4ab9faab3bbd4489e483/fastar-0.8.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:a3253a06845462ca2196024c7a18f5c0ba4de1532ab1c4bad23a40b332a06a6a", size = 706112, upload-time = "2025-11-26T02:34:39.237Z" }, - { url = "https://files.pythonhosted.org/packages/0a/03/4f883bce878218a8676c2d7ca09b50c856a5470bb3b7f63baf9521ea6995/fastar-0.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5cbeb3ebfa0980c68ff8b126295cc6b208ccd81b638aebc5a723d810a7a0e5d2", size = 628954, upload-time = "2025-11-26T02:34:23.705Z" }, - { url = "https://files.pythonhosted.org/packages/4f/f1/892e471f156b03d10ba48ace9384f5a896702a54506137462545f38e40b8/fastar-0.8.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1c0d5956b917daac77d333d48b3f0f3ff927b8039d5b32d8125462782369f761", size = 868685, upload-time = "2025-11-26T02:33:53.077Z" }, - { url = "https://files.pythonhosted.org/packages/39/ba/e24915045852e30014ec6840446975c03f4234d1c9270394b51d3ad18394/fastar-0.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27b404db2b786b65912927ce7f3790964a4bcbde42cdd13091b82a89cd655e1c", size = 765044, upload-time = "2025-11-26T02:32:48.187Z" }, - { url = "https://files.pythonhosted.org/packages/14/2c/1aa11ac21a99984864c2fca4994e094319ff3a2046e7a0343c39317bd5b9/fastar-0.8.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0902fc89dcf1e7f07b8563032a4159fe2b835e4c16942c76fd63451d0e5f76a3", size = 764322, upload-time = "2025-11-26T02:33:03.859Z" }, - { url = "https://files.pythonhosted.org/packages/ba/f0/4b91902af39fe2d3bae7c85c6d789586b9fbcf618d7fdb3d37323915906d/fastar-0.8.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:069347e2f0f7a8b99bbac8cd1bc0e06c7b4a31dc964fc60d84b95eab3d869dc1", size = 931016, upload-time = "2025-11-26T02:33:19.902Z" }, - { url = "https://files.pythonhosted.org/packages/c9/97/8fc43a5a9c0a2dc195730f6f7a0f367d171282cd8be2511d0e87c6d2dad0/fastar-0.8.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fd135306f6bfe9a835918280e0eb440b70ab303e0187d90ab51ca86e143f70d", size = 821308, upload-time = "2025-11-26T02:33:34.664Z" }, - { url = "https://files.pythonhosted.org/packages/0c/e9/058615b63a7fd27965e8c5966f393ed0c169f7ff5012e1674f21684de3ba/fastar-0.8.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d06d6897f43c27154b5f2d0eb930a43a81b7eec73f6f0b0114814d4a10ab38", size = 821171, upload-time = "2025-11-26T02:34:08.498Z" }, - { url = "https://files.pythonhosted.org/packages/ca/cf/69e16a17961570a755c37ffb5b5aa7610d2e77807625f537989da66f2a9d/fastar-0.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a922f8439231fa0c32b15e8d70ff6d415619b9d40492029dabbc14a0c53b5f18", size = 986227, upload-time = "2025-11-26T02:34:55.06Z" }, - { url = "https://files.pythonhosted.org/packages/fb/83/2100192372e59b56f4ace37d7d9cabda511afd71b5febad1643d1c334271/fastar-0.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a739abd51eb766384b4caff83050888e80cd75bbcfec61e6d1e64875f94e4a40", size = 1039395, upload-time = "2025-11-26T02:35:12.166Z" }, - { url = "https://files.pythonhosted.org/packages/75/15/cdd03aca972f55872efbb7cf7540c3fa7b97a75d626303a3ea46932163dc/fastar-0.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5a65f419d808b23ac89d5cd1b13a2f340f15bc5d1d9af79f39fdb77bba48ff1b", size = 1044766, upload-time = "2025-11-26T02:35:29.62Z" }, - { url = "https://files.pythonhosted.org/packages/3d/29/945e69e4e2652329ace545999334ec31f1431fbae3abb0105587e11af2ae/fastar-0.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7bb2ae6c0cce58f0db1c9f20495e7557cca2c1ee9c69bbd90eafd54f139171c5", size = 994740, upload-time = "2025-11-26T02:35:47.887Z" }, - { url = "https://files.pythonhosted.org/packages/4b/5d/dbfe28f8cd1eb484bba0c62e5259b2cf6fea229d6ef43e05c06b5a78c034/fastar-0.8.0-cp313-cp313-win32.whl", hash = "sha256:b28753e0d18a643272597cb16d39f1053842aa43131ad3e260c03a2417d38401", size = 455990, upload-time = "2025-11-26T02:36:28.502Z" }, - { url = "https://files.pythonhosted.org/packages/e1/01/e965740bd36e60ef4c5aa2cbe42b6c4eb1dc3551009238a97c2e5e96bd23/fastar-0.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:620e5d737dce8321d49a5ebb7997f1fd0047cde3512082c27dc66d6ac8c1927a", size = 490227, upload-time = "2025-11-26T02:36:14.363Z" }, - { url = "https://files.pythonhosted.org/packages/dd/10/c99202719b83e5249f26902ae53a05aea67d840eeb242019322f20fc171c/fastar-0.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:c4c4bd08df563120cd33e854fe0a93b81579e8571b11f9b7da9e84c37da2d6b6", size = 461078, upload-time = "2025-11-26T02:36:04.94Z" }, - { url = "https://files.pythonhosted.org/packages/96/4a/9573b87a0ef07580ed111e7230259aec31bb33ca3667963ebee77022ec61/fastar-0.8.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:50b36ce654ba44b0e13fae607ae17ee6e1597b69f71df1bee64bb8328d881dfc", size = 706041, upload-time = "2025-11-26T02:34:40.638Z" }, - { url = "https://files.pythonhosted.org/packages/4a/19/f95444a1d4f375333af49300aa75ee93afa3335c0e40fda528e460ed859c/fastar-0.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:63a892762683d7ab00df0227d5ea9677c62ff2cde9b875e666c0be569ed940f3", size = 628617, upload-time = "2025-11-26T02:34:24.893Z" }, - { url = "https://files.pythonhosted.org/packages/b3/c9/b51481b38b7e3f16ef2b9e233b1a3623386c939d745d6e41bbd389eaae30/fastar-0.8.0-cp314-cp314-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4ae6a145c1bff592644bde13f2115e0239f4b7babaf506d14e7d208483cf01a5", size = 869299, upload-time = "2025-11-26T02:33:54.274Z" }, - { url = "https://files.pythonhosted.org/packages/bf/02/3ba1267ee5ba7314e29c431cf82eaa68586f2c40cdfa08be3632b7d07619/fastar-0.8.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ae0ff7c0a1c7e1428404b81faee8aebef466bfd0be25bfe4dabf5d535c68741", size = 764667, upload-time = "2025-11-26T02:32:49.606Z" }, - { url = "https://files.pythonhosted.org/packages/1b/84/bf33530fd015b5d7c2cc69e0bce4a38d736754a6955487005aab1af6adcd/fastar-0.8.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dbfd87dbd217b45c898b2dbcd0169aae534b2c1c5cbe3119510881f6a5ac8ef5", size = 763993, upload-time = "2025-11-26T02:33:05.782Z" }, - { url = "https://files.pythonhosted.org/packages/da/e0/9564d24e7cea6321a8d921c6d2a457044a476ef197aa4708e179d3d97f0d/fastar-0.8.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a5abd99fcba83ef28c8fe6ae2927edc79053db43a0457a962ed85c9bf150d37", size = 930153, upload-time = "2025-11-26T02:33:21.53Z" }, - { url = "https://files.pythonhosted.org/packages/35/b1/6f57fcd8d6e192cfebf97e58eb27751640ad93784c857b79039e84387b51/fastar-0.8.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91d4c685620c3a9d6b5ae091dbabab4f98b20049b7ecc7976e19cc9016c0d5d6", size = 821177, upload-time = "2025-11-26T02:33:35.839Z" }, - { url = "https://files.pythonhosted.org/packages/b3/78/9e004ea9f3aa7466f5ddb6f9518780e1d2f0ed3ca55f093632982598bace/fastar-0.8.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f77c2f2cad76e9dc7b6701297adb1eba87d0485944b416fc2ccf5516c01219a3", size = 820652, upload-time = "2025-11-26T02:34:09.776Z" }, - { url = "https://files.pythonhosted.org/packages/42/95/b604ed536544005c9f1aee7c4c74b00150db3d8d535cd8232dc20f947063/fastar-0.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e7f07c4a3dada7757a8fc430a5b4a29e6ef696d2212747213f57086ffd970316", size = 985961, upload-time = "2025-11-26T02:34:56.401Z" }, - { url = "https://files.pythonhosted.org/packages/f2/7b/fa9d4d96a5d494bdb8699363bb9de8178c0c21a02e1d89cd6f913d127018/fastar-0.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:90c0c3fe55105c0aed8a83135dbdeb31e683455dbd326a1c48fa44c378b85616", size = 1039316, upload-time = "2025-11-26T02:35:13.807Z" }, - { url = "https://files.pythonhosted.org/packages/4e/f9/8462789243bc3f33e8401378ec6d54de4e20cfa60c96a0e15e3e9d1389bb/fastar-0.8.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:fb9ee51e5bffe0dab3d3126d3a4fac8d8f7235cedcb4b8e74936087ce1c157f3", size = 1045028, upload-time = "2025-11-26T02:35:31.079Z" }, - { url = "https://files.pythonhosted.org/packages/a5/71/9abb128777e616127194b509e98fcda3db797d76288c1a8c23dd22afc14f/fastar-0.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e380b1e8d30317f52406c43b11e98d11e1d68723bbd031e18049ea3497b59a6d", size = 994677, upload-time = "2025-11-26T02:35:49.391Z" }, - { url = "https://files.pythonhosted.org/packages/de/c1/b81b3f194853d7ad232a67a1d768f5f51a016f165cfb56cb31b31bbc6177/fastar-0.8.0-cp314-cp314-win32.whl", hash = "sha256:1c4ffc06e9c4a8ca498c07e094670d8d8c0d25b17ca6465b9774da44ea997ab1", size = 456687, upload-time = "2025-11-26T02:36:30.205Z" }, - { url = "https://files.pythonhosted.org/packages/cb/87/9e0cd4768a98181d56f0cdbab2363404cc15deb93f4aad3b99cd2761bbaa/fastar-0.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:5517a8ad4726267c57a3e0e2a44430b782e00b230bf51c55b5728e758bb3a692", size = 490578, upload-time = "2025-11-26T02:36:16.218Z" }, - { url = "https://files.pythonhosted.org/packages/aa/1e/580a76cf91847654f2ad6520e956e93218f778540975bc4190d363f709e2/fastar-0.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:58030551046ff4a8616931e52a36c83545ff05996db5beb6e0cd2b7e748aa309", size = 461473, upload-time = "2025-11-26T02:36:06.373Z" }, - { url = "https://files.pythonhosted.org/packages/58/4c/bdb5c6efe934f68708529c8c9d4055ebef5c4be370621966438f658b29bd/fastar-0.8.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:1e7d29b6bfecb29db126a08baf3c04a5ab667f6cea2b7067d3e623a67729c4a6", size = 705570, upload-time = "2025-11-26T02:34:42.01Z" }, - { url = "https://files.pythonhosted.org/packages/6d/78/f01ac7e71d5a37621bd13598a26e948a12b85ca8042f7ee1a0a8c9f59cda/fastar-0.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:05eb7b96940f9526b485f1d0b02393839f0f61cac4b1f60024984f8b326d2640", size = 627761, upload-time = "2025-11-26T02:34:26.152Z" }, - { url = "https://files.pythonhosted.org/packages/06/45/6df0ecda86ea9d2e95053c1a655d153dee55fc121b6e13ea6d1e246a50b6/fastar-0.8.0-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:619352d8ac011794e2345c462189dc02ba634750d23cd9d86a9267dd71b1f278", size = 869414, upload-time = "2025-11-26T02:33:55.618Z" }, - { url = "https://files.pythonhosted.org/packages/b2/72/486421f5a8c0c377cc82e7a50c8a8ea899a6ec2aa72bde8f09fb667a2dc8/fastar-0.8.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74ebfecef3fe6d7a90355fac1402fd30636988332a1d33f3e80019a10782bb24", size = 763863, upload-time = "2025-11-26T02:32:51.051Z" }, - { url = "https://files.pythonhosted.org/packages/d4/64/39f654dbb41a3867fb1f2c8081c014d8f1d32ea10585d84cacbef0b32995/fastar-0.8.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2975aca5a639e26a3ab0d23b4b0628d6dd6d521146c3c11486d782be621a35aa", size = 763065, upload-time = "2025-11-26T02:33:07.274Z" }, - { url = "https://files.pythonhosted.org/packages/4e/bd/c011a34fb3534c4c3301f7c87c4ffd7e47f6113c904c092ddc8a59a303ea/fastar-0.8.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afc438eaed8ff0dcdd9308268be5cb38c1db7e94c3ccca7c498ca13a4a4535a3", size = 930530, upload-time = "2025-11-26T02:33:23.117Z" }, - { url = "https://files.pythonhosted.org/packages/55/9d/aa6e887a7033c571b1064429222bbe09adc9a3c1e04f3d1788ba5838ebd5/fastar-0.8.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6ced0a5399cc0a84a858ef0a31ca2d0c24d3bbec4bcda506a9192d8119f3590a", size = 820572, upload-time = "2025-11-26T02:33:37.542Z" }, - { url = "https://files.pythonhosted.org/packages/ad/9c/7a3a2278a1052e1a5d98646de7c095a00cffd2492b3b84ce730e2f1cd93a/fastar-0.8.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec9b23da8c4c039da3fe2e358973c66976a0c8508aa06d6626b4403cb5666c19", size = 820649, upload-time = "2025-11-26T02:34:11.108Z" }, - { url = "https://files.pythonhosted.org/packages/02/9e/d38edc1f4438cd047e56137c26d94783ffade42e1b3bde620ccf17b771ef/fastar-0.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:dfba078fcd53478032fd0ceed56960ec6b7ff0511cfc013a8a3a4307e3a7bac4", size = 985653, upload-time = "2025-11-26T02:34:57.884Z" }, - { url = "https://files.pythonhosted.org/packages/69/d9/2147d0c19757e165cd62d41cec3f7b38fad2ad68ab784978b5f81716c7ea/fastar-0.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:ade56c94c14be356d295fecb47a3fcd473dd43a8803ead2e2b5b9e58feb6dcfa", size = 1038140, upload-time = "2025-11-26T02:35:15.778Z" }, - { url = "https://files.pythonhosted.org/packages/7f/1d/ec4c717ffb8a308871e9602ec3197d957e238dc0227127ac573ec9bca952/fastar-0.8.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e48d938f9366db5e59441728f70b7f6c1ccfab7eff84f96f9b7e689b07786c52", size = 1045195, upload-time = "2025-11-26T02:35:32.865Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9f/637334dc8c8f3bb391388b064ae13f0ad9402bc5a6c3e77b8887d0c31921/fastar-0.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:79c441dc1482ff51a54fb3f57ae6f7bb3d2cff88fa2cc5d196c519f8aab64a56", size = 994686, upload-time = "2025-11-26T02:35:51.392Z" }, - { url = "https://files.pythonhosted.org/packages/c9/e2/dfa19a4b260b8ab3581b7484dcb80c09b25324f4daa6b6ae1c7640d1607a/fastar-0.8.0-cp314-cp314t-win32.whl", hash = "sha256:187f61dc739afe45ac8e47ed7fd1adc45d52eac110cf27d579155720507d6fbe", size = 455767, upload-time = "2025-11-26T02:36:34.758Z" }, - { url = "https://files.pythonhosted.org/packages/51/47/df65c72afc1297797b255f90c4778b5d6f1f0f80282a134d5ab610310ed9/fastar-0.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:40e9d763cf8bf85ce2fa256e010aa795c0fe3d3bd1326d5c3084e6ce7857127e", size = 489971, upload-time = "2025-11-26T02:36:22.081Z" }, - { url = "https://files.pythonhosted.org/packages/85/11/0aa8455af26f0ae89e42be67f3a874255ee5d7f0f026fc86e8d56f76b428/fastar-0.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:e59673307b6a08210987059a2bdea2614fe26e3335d0e5d1a3d95f49a05b1418", size = 460467, upload-time = "2025-11-26T02:36:07.978Z" }, - { url = "https://files.pythonhosted.org/packages/25/9f/6eaa810c240236eff2edf736cd50a17c97dbab1693cda4f7bcea09d13418/fastar-0.8.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2127cf2e80ffd49744a160201e0e2f55198af6c028a7b3f750026e0b1f1caa4e", size = 710544, upload-time = "2025-11-26T02:34:46.195Z" }, - { url = "https://files.pythonhosted.org/packages/1d/a5/58ff9e49a1cd5fbfc8f1238226cbf83b905376a391a6622cdd396b2cfa29/fastar-0.8.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:ff85094f10003801339ac4fa9b20a3410c2d8f284d4cba2dc99de6e98c877812", size = 634020, upload-time = "2025-11-26T02:34:31.085Z" }, - { url = "https://files.pythonhosted.org/packages/80/94/f839257c6600a83fbdb5a7fcc06319599086137b25ba38ca3d2c0fe14562/fastar-0.8.0-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3dbca235f0bd804cca6602fe055d3892bebf95fb802e6c6c7d872fb10f7abc6c", size = 871735, upload-time = "2025-11-26T02:34:00.088Z" }, - { url = "https://files.pythonhosted.org/packages/eb/79/4124c54260f7ee5cb7034bfe499eff2f8512b052d54be4671e59d4f25a4f/fastar-0.8.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e54bfdee6c81a0005e147319e93d8797f442308032c92fa28d03ef8fda076", size = 766779, upload-time = "2025-11-26T02:32:55.109Z" }, - { url = "https://files.pythonhosted.org/packages/36/b6/043b263c4126bf6557c942d099503989af9c5c7ee5cca9a04e00f754816f/fastar-0.8.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a78e5221b94a80800930b7fd0d0e797ae73aadf7044c05ed46cb9bdf870f022", size = 766755, upload-time = "2025-11-26T02:33:11.595Z" }, - { url = "https://files.pythonhosted.org/packages/57/ff/29a5dc06f2940439ebf98661ecc98d48d3f22fed8d6a2d5dc985d1e8da24/fastar-0.8.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:997092d31ff451de8d0568f6773f3517cb87dcd0bc76184edb65d7154390a6f8", size = 932732, upload-time = "2025-11-26T02:33:27.122Z" }, - { url = "https://files.pythonhosted.org/packages/eb/e8/2218830f422b37aad52c24b53cb84b5d88bd6fd6ad411bd6689b1a32500d/fastar-0.8.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:558e8fcf8fe574541df5db14a46cd98bfbed14a811b7014a54f2b714c0cfac42", size = 822571, upload-time = "2025-11-26T02:33:42.986Z" }, - { url = "https://files.pythonhosted.org/packages/6e/fd/ba6dfeff77cddfe58d85c490b1735c002b81c0d6f826916a8b6c4f8818bc/fastar-0.8.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1d2a54f87e2908cc19e1a6ee249620174fbefc54a219aba1eaa6f31657683c3", size = 822440, upload-time = "2025-11-26T02:34:15.439Z" }, - { url = "https://files.pythonhosted.org/packages/a7/57/54d5740c84b35de0eb12975397ecc16785b5ad8bed2dbac38b8c8a7c1edd/fastar-0.8.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:ef94901537be277f9ec59db939eb817960496c6351afede5b102699b5098604d", size = 987424, upload-time = "2025-11-26T02:35:02.742Z" }, - { url = "https://files.pythonhosted.org/packages/ee/c7/18115927f16deb1ddffdbd4ae992e7e33064bc6defa2b92a147948f8bc0c/fastar-0.8.0-pp310-pypy310_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:0afbb92f78bf29d5e9db76fb46cbabc429e49015cddf72ab9e761afbe88ac100", size = 1042675, upload-time = "2025-11-26T02:35:20.252Z" }, - { url = "https://files.pythonhosted.org/packages/d7/1a/ca884fc7973ec6d765e87af23a4dd25784fb0a36ac2df825f18c3630bbab/fastar-0.8.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:fb59c7925e7710ad178d9e1a3e65edf295d9a042a0cdcb673b4040949eb8ad0a", size = 1047098, upload-time = "2025-11-26T02:35:37.643Z" }, - { url = "https://files.pythonhosted.org/packages/44/ee/25cd645db749b206bb95e1512e57e75d56ccbbb8ec3536f52a7979deab6b/fastar-0.8.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e6c4d6329da568ec36b1347b0c09c4d27f9dfdeddf9f438ddb16799ecf170098", size = 997397, upload-time = "2025-11-26T02:35:56.215Z" }, - { url = "https://files.pythonhosted.org/packages/98/6e/6c46aa7f8c8734e7f96ee5141acd3877667ce66f34eea10703aa7571d191/fastar-0.8.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:998e3fa4b555b63eb134e6758437ed739ad1652fdd2a61dfe1dacbfddc35fe66", size = 710662, upload-time = "2025-11-26T02:34:47.593Z" }, - { url = "https://files.pythonhosted.org/packages/70/27/fd622442f2fbd4ff5459677987481ef1c60e077cb4e63a2ed4d8dce6f869/fastar-0.8.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:5f83e60d845091f3a12bc37f412774264d161576eaf810ed8b43567eb934b7e5", size = 634049, upload-time = "2025-11-26T02:34:32.365Z" }, - { url = "https://files.pythonhosted.org/packages/8f/ee/aa4d08aea25b5419a7277132e738ab1cd775f26aebddce11413b07e2fdff/fastar-0.8.0-pp311-pypy311_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:299672e1c74d8b73c61684fac9159cfc063d35f4b165996a88facb0e26862cb5", size = 872055, upload-time = "2025-11-26T02:34:01.377Z" }, - { url = "https://files.pythonhosted.org/packages/92/9a/2bf2f77aade575e67997e0c759fd55cb1c66b7a5b437b1cd0e97d8b241bc/fastar-0.8.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3d3a27066b84d015deab5faee78565509bb33b137896443e4144cb1be1a5f90", size = 766787, upload-time = "2025-11-26T02:32:57.161Z" }, - { url = "https://files.pythonhosted.org/packages/0b/90/23a3f6c252f11b10c70f854bce09abc61f71b5a0e6a4b0eac2bcb9a2c583/fastar-0.8.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ef0bcf4385bbdd3c1acecce2d9ea7dab7cc9b8ee0581bbccb7ab11908a7ce288", size = 766861, upload-time = "2025-11-26T02:33:12.824Z" }, - { url = "https://files.pythonhosted.org/packages/76/bb/beeb9078380acd4484db5c957d066171695d9340e3526398eb230127b0c2/fastar-0.8.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f10ef62b6eda6cb6fd9ba8e1fe08a07d7b2bdcc8eaa00eb91566143b92ed7eee", size = 932667, upload-time = "2025-11-26T02:33:28.405Z" }, - { url = "https://files.pythonhosted.org/packages/f4/6d/b034cc637bd0ee638d5a85d08e941b0b8ffd44cf391fb751ba98233734f7/fastar-0.8.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c4f6c82a8ee98c17aa48585ee73b51c89c1b010e5c951af83e07c3436180e3fc", size = 822712, upload-time = "2025-11-26T02:33:44.27Z" }, - { url = "https://files.pythonhosted.org/packages/e2/2b/7d183c63f59227c4689792042d6647f2586a5e7273b55e81745063088d81/fastar-0.8.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6129067fcb86276635b5857010f4e9b9c7d5d15dd571bb03c6c1ed73c40fd92", size = 822659, upload-time = "2025-11-26T02:34:16.815Z" }, - { url = "https://files.pythonhosted.org/packages/3e/f9/716e0cd9de2427fdf766bc68176f76226cd01fffef3a56c5046fa863f5f0/fastar-0.8.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4cc9e77019e489f1ddac446b6a5b9dfb5c3d9abd142652c22a1d9415dbcc0e47", size = 987412, upload-time = "2025-11-26T02:35:04.259Z" }, - { url = "https://files.pythonhosted.org/packages/a4/b9/9a8c3fd59958c1c8027bc075af11722cdc62c4968bb277e841d131232289/fastar-0.8.0-pp311-pypy311_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:382bfe82c026086487cb17fee12f4c1e2b4e67ce230f2e04487d3e7ddfd69031", size = 1042911, upload-time = "2025-11-26T02:35:21.857Z" }, - { url = "https://files.pythonhosted.org/packages/e2/2f/c3f30963b47022134b8a231c12845f4d7cfba520f59bbc1a82468aea77c7/fastar-0.8.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:908d2b9a1ff3d549cc304b32f95706a536da8f0bcb0bc0f9e4c1cce39b80e218", size = 1047464, upload-time = "2025-11-26T02:35:39.376Z" }, - { url = "https://files.pythonhosted.org/packages/9e/8a/218ab6d9a2bab3b07718e6cd8405529600edc1e9c266320e8524c8f63251/fastar-0.8.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:1aa7dbde2d2d73eb5b6203d0f74875cb66350f0f1b4325b4839fc8fbbf5d074e", size = 997309, upload-time = "2025-11-26T02:35:57.722Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/dd/00/dab9ca274cf1fde19223fea7104631bea254751026e75bf99f2b6d0d1568/fastar-0.9.0.tar.gz", hash = "sha256:d49114d5f0b76c5cc242875d90fa4706de45e0456ddedf416608ecd0787fb410", size = 70124, upload-time = "2026-03-20T14:26:34.503Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/24/48/3d8e24c9ae7796e59231f50133640463c6a20b00ce684b308dc6de0e28fe/fastar-0.9.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:19a384395f26daa3ecb6c24054f3a50ce919e250e06b82614a252a0fadcbca17", size = 709092, upload-time = "2026-03-20T14:25:30.007Z" }, + { url = "https://files.pythonhosted.org/packages/d9/e5/4d7dc06f3ad5457b9a1510a75e3f9ec431ad020688fcf954012a2bcae6e8/fastar-0.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b9c82b1fef26d8fd4abad1152f4c74eeb86bc9d46c814757b695847a751b9b0b", size = 630252, upload-time = "2026-03-20T14:25:17.673Z" }, + { url = "https://files.pythonhosted.org/packages/79/d4/ebb285a263cc2070d04d39917288b5d1c7f49e1c47ed5544e86283e091c6/fastar-0.9.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e5c91cb4527a6e634e7477a01aa52ccfbb978df1d9803172685c1e0802a2c18c", size = 869584, upload-time = "2026-03-20T14:24:52.067Z" }, + { url = "https://files.pythonhosted.org/packages/23/19/a293b6f75ea1b9e14d384859253ee65f966a73be306cea39552a557c9e34/fastar-0.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6bc32f40a3e8ab12b8ebce48c4808d2bcf89bd3dac3023980b8a9b4aaf719f2", size = 762379, upload-time = "2026-03-20T14:23:47.429Z" }, + { url = "https://files.pythonhosted.org/packages/95/2f/a31f00c31f16a3bffd6f6ab3414964100fb35a79983f21283fc8b81d3cec/fastar-0.9.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ee4a1d85a58cd955a5409b221450762b851879ce6e080d6d717265fb9a4e939d", size = 759567, upload-time = "2026-03-20T14:24:00.677Z" }, + { url = "https://files.pythonhosted.org/packages/b0/46/5a4b1fb1e5c8b6cd1eb464e658ed75d667f1f53834f353e6323ca71bd113/fastar-0.9.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b72e25ec1cbad0fc2a5f93a147978cc41e054ce5789807ebd3bcece5f276c0c2", size = 925850, upload-time = "2026-03-20T14:24:13.669Z" }, + { url = "https://files.pythonhosted.org/packages/f6/ec/a5543fb1b059a82ce4c6fc571fe429390294e8150c09bb537d228471eac6/fastar-0.9.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9862ddfaf73c7388d708bcbeb75e2e336605465b88d952407621c847bab5d3cb", size = 818858, upload-time = "2026-03-20T14:24:39.431Z" }, + { url = "https://files.pythonhosted.org/packages/53/9a/af5ae6d24e1170702d096225989b4ee3470b22bbecb5c09c899e816aefd7/fastar-0.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3471fa2627b9703830d13c8b0a6ba19eeff4e2e0ff924631065ecceca56abb2b", size = 821941, upload-time = "2026-03-20T14:25:05.534Z" }, + { url = "https://files.pythonhosted.org/packages/54/3f/399d8b080f7c5fe1fa88dadaa7a30bd0bb885ad490d3c2ef2c667877c5c4/fastar-0.9.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:e3d2e68e0239ab24b65b0674f2b74ac71d8fb5ea221a3e0d0ab966292bd83e12", size = 886548, upload-time = "2026-03-20T14:24:26.209Z" }, + { url = "https://files.pythonhosted.org/packages/63/cd/034b5f61e99df67e092e1d3d538150a5f562d00c0259e6402cbcb62e15a9/fastar-0.9.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dcabfe31c48ff6a994c3dc4ddc27287b15d78a09c737beef8a6b1f210b720a6a", size = 970244, upload-time = "2026-03-20T14:25:42.928Z" }, + { url = "https://files.pythonhosted.org/packages/3e/8f/3a8b0d711050b300a3448c9d145c6d234958e148e456ab4a15daca6e4b05/fastar-0.9.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:f1723bb9cc3dcd087b5dd066a0369f27529a925d467ccc896d1f6cd0212417bf", size = 1036944, upload-time = "2026-03-20T14:25:55.867Z" }, + { url = "https://files.pythonhosted.org/packages/34/11/cd5ebd16529c5fbff2431b494bd6f3f8ecafeca8f874449bf65ccf58c77b/fastar-0.9.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3ec2e699af02ba78f359b1cf1f4b3da22f41dec3a327f1cda6a1d31a43365a71", size = 1078612, upload-time = "2026-03-20T14:26:09.042Z" }, + { url = "https://files.pythonhosted.org/packages/85/c7/752c184e3c5e8de592e5d7ce3d081bf665ae5dbbe4a3df816daf38043143/fastar-0.9.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:761708eb2f6e402d4cda04ac81d0c2406b1c10375601e238083d2e885ec52a42", size = 1029368, upload-time = "2026-03-20T14:26:21.79Z" }, + { url = "https://files.pythonhosted.org/packages/68/b3/2a5551942adaecb9874ebc0d0922f3ab9dd058298b7a36a7900da93a3e68/fastar-0.9.0-cp310-cp310-win32.whl", hash = "sha256:a5ea0969c94845faed7bf681850df704da9617ad7231850dbc7ca4017080133a", size = 454507, upload-time = "2026-03-20T14:26:54.124Z" }, + { url = "https://files.pythonhosted.org/packages/23/30/7a2f25837ee7353ff5eaa815d9a6321f8704fcc39a94570a1b2d958639c0/fastar-0.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:e5646f10a747282904f2def929612ed19cace4bd702029c3d7c78205ef604abd", size = 486500, upload-time = "2026-03-20T14:26:42.142Z" }, + { url = "https://files.pythonhosted.org/packages/6f/01/4ecbe0b4938608f9c6c5c4d4f6b872975fe30152bfaa8e44fe0e3b6cbcc4/fastar-0.9.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:facc7522bd1c1e7569bedb602932fc7292408a320f415d72180634d58f661bf0", size = 708809, upload-time = "2026-03-20T14:25:31.299Z" }, + { url = "https://files.pythonhosted.org/packages/11/6a/085b3cae0e04da4d42306dc07e2cc4f95d9c8f27df4dfd1a25d0f80516cb/fastar-0.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c8ac3e8aaee57dfc822b04f570f0a963c2381a9dc8990fe0c6e965efd23fd451", size = 629764, upload-time = "2026-03-20T14:25:19.017Z" }, + { url = "https://files.pythonhosted.org/packages/3c/c2/cdd996a37837e6cc5edc4d09775d2a2bc63e9e931129db69947cf4c77148/fastar-0.9.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d90493b4bb56db728b38eb18a551df386113d72ad4e7f1a97572f3662a9b8a85", size = 869631, upload-time = "2026-03-20T14:24:53.779Z" }, + { url = "https://files.pythonhosted.org/packages/30/d4/4a5a3c341d26197ea3ae6bed79fc9bb4ead8ddc74a93bdb74e4ee0bac18e/fastar-0.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17e2c3b46408193ea13c1e1177275ca7951e88bd3dce16baccb8de4f5e0dc2e8", size = 762096, upload-time = "2026-03-20T14:23:49.175Z" }, + { url = "https://files.pythonhosted.org/packages/bc/dd/1d346cdfcd3064f6c435eff90a8d7cf0021487e3681453bdd681b9488d81/fastar-0.9.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:52f96a3d4cfbe4f06b376706fa0562f3a1d2329bc37168119af0e47e1ac21cab", size = 759627, upload-time = "2026-03-20T14:24:01.984Z" }, + { url = "https://files.pythonhosted.org/packages/02/a1/e91eb7ae1e41c0d3ead86dc199beb13a0b80101e2948d66adeb578b09e60/fastar-0.9.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57e9b94e485713c79bb259f7ecff1213527d05e9aa43a157c3fbc88812cf163e", size = 926211, upload-time = "2026-03-20T14:24:15.218Z" }, + { url = "https://files.pythonhosted.org/packages/9b/63/9fea9604e7aecc2f062f0df5729f74712d81615a1b18fa6a1a13106184fa/fastar-0.9.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fb06d0a0cc3cf52a9c07559bb16ab99eb75afe0b3d5ce68f5c299569460851ac", size = 818748, upload-time = "2026-03-20T14:24:40.765Z" }, + { url = "https://files.pythonhosted.org/packages/b0/f8/521438041d69873bb68b144b09080ae4f1621cebb8238b1e54821057206b/fastar-0.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c75e779f72d845037d4bf6692d01ac66f014eaef965c9231d41d5cc1276b89fc", size = 822380, upload-time = "2026-03-20T14:25:06.825Z" }, + { url = "https://files.pythonhosted.org/packages/92/05/f33cc3f5f96ffb7d81a7f06c9239d4eea584527292a030a73d3218148f41/fastar-0.9.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:24b13fc4ef3f1e3c9cc2dcf07ad9445900db9d3ce09b73021547a55994d0407f", size = 886569, upload-time = "2026-03-20T14:24:27.567Z" }, + { url = "https://files.pythonhosted.org/packages/60/32/6e7cb45dce544f97b0199325084a0a5a895cb903e0539690619e78d8d7cf/fastar-0.9.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec7852de506d022ad36ad56f4aefb10c259dd59e485bf87af827954d404ba9d5", size = 969993, upload-time = "2026-03-20T14:25:44.222Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ee/04cf9374e5e6a82ddc87073d684c1fa7a9ca368bf85c2786535b1bfc38a9/fastar-0.9.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:a79c53c3003958dca88a7ec3dd805bf9c2fb2a659110039f44571d57e329e3d4", size = 1036738, upload-time = "2026-03-20T14:25:57.551Z" }, + { url = "https://files.pythonhosted.org/packages/b6/94/e6f6ad29c25c5f531a406e3a35ef5c034ea177748f9fb621073519adb3d5/fastar-0.9.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:00328ce7ae76be7f9e2faa6a221a0b41212e4115c27e2ac5e585bcf226bfc2eb", size = 1078557, upload-time = "2026-03-20T14:26:10.358Z" }, + { url = "https://files.pythonhosted.org/packages/1f/44/a1c9f6afe93d1cc1abb68a7cda2bada509d756d24e22d5d949ca86b4f45e/fastar-0.9.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5c03fad1ad9ac57cf03a4db9e18c7109c37416ff4eb9ebfca98fcd2b233a26c4", size = 1029251, upload-time = "2026-03-20T14:26:23.215Z" }, + { url = "https://files.pythonhosted.org/packages/75/31/9e77bc2af3c8b8a433b7175d14b9c75d0ab901542c7452fdf942ece5a155/fastar-0.9.0-cp311-cp311-win32.whl", hash = "sha256:163ba4c543d2112c8186be2f134d11456b593071ba9ea3faba4f155bde7c5dac", size = 454633, upload-time = "2026-03-20T14:26:55.344Z" }, + { url = "https://files.pythonhosted.org/packages/0c/d4/a78d51d1290cdce2d6d3162a18d12c736b71d3feef5a446b3fe021443eb3/fastar-0.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:2137d5d26044b44bb19197a8fc959256c772615ee959cddd0f74320b548fc966", size = 486772, upload-time = "2026-03-20T14:26:43.569Z" }, + { url = "https://files.pythonhosted.org/packages/fa/39/471aefca4c8180689cc0dc6f2f23bc283a3ca07114f713307fb947d320af/fastar-0.9.0-cp311-cp311-win_arm64.whl", hash = "sha256:ecb94de3bc96d9fae95641a7907385541517a4c17416153d3b952d37dce0a2a3", size = 463586, upload-time = "2026-03-20T14:26:35.483Z" }, + { url = "https://files.pythonhosted.org/packages/4d/9b/300bc0dafa8495718976076db216f42d57b251a582589566a63b4ed2cb82/fastar-0.9.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7a8b5daa50d9b4c07367dffc40880467170bf1c31ca63a2286506edbe6d3d65b", size = 706914, upload-time = "2026-03-20T14:25:32.501Z" }, + { url = "https://files.pythonhosted.org/packages/95/97/f1e34c8224dc373c6fab5b33e33be0d184751fdc27013af3278b1e4e6e6c/fastar-0.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ec841a69fea73361c6df6d9183915c09e9ce3bd96493763fa46019e79918400", size = 627422, upload-time = "2026-03-20T14:25:20.318Z" }, + { url = "https://files.pythonhosted.org/packages/a9/ad/e2499d136e24c2d896f2ec58183c91c6f8185d758177537724ed2f3e1b54/fastar-0.9.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ad46bc23040142e9be4b4005ea366834dbf0f1b6a90b8ecdc3ec96c42dec4adf", size = 865265, upload-time = "2026-03-20T14:24:55.418Z" }, + { url = "https://files.pythonhosted.org/packages/fe/cf/b6ad68b2ab1d7b74b0d38725d817418016bdd64880b36108be80d2460b4d/fastar-0.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de264da9e8ef6407aa0b23c7c47ed4e34fde867e7c1f6e3cb98945a93e5f89f2", size = 760583, upload-time = "2026-03-20T14:23:50.447Z" }, + { url = "https://files.pythonhosted.org/packages/b8/96/086116ad46e3b98f6c217919d680e619f2857ffa6b5cc0d7e46e4f214b83/fastar-0.9.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:75c70be3a7da3ff9342f64c15ec3749c13ef56bc28e69075d82d03768532a8d0", size = 758000, upload-time = "2026-03-20T14:24:03.471Z" }, + { url = "https://files.pythonhosted.org/packages/9b/e6/ea642ea61eea98d609343080399a296a9ff132bd0492a6638d6e0d9e41a7/fastar-0.9.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a734506b071d2a8844771fe735fbd6d67dd0eec80eef5f189bbe763ebe7a0b8", size = 923647, upload-time = "2026-03-20T14:24:16.875Z" }, + { url = "https://files.pythonhosted.org/packages/c6/3e/53874aad61e4a664af555a2aa7a52fe46cfadd423db0e592fa0cfe0fa668/fastar-0.9.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8eac084ab215aaf65fa406c9b9da1ac4e697c3d3a1a183e09c488e555802f62d", size = 816528, upload-time = "2026-03-20T14:24:42.048Z" }, + { url = "https://files.pythonhosted.org/packages/41/df/d663214d35380b07a24a796c48d7d7d4dc3a28ec0756edbcb7e2a81dc572/fastar-0.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acb62e2369834fb23d26327157f0a2dbec40b230c709fa85b1ce96cf010e6fbf", size = 819050, upload-time = "2026-03-20T14:25:08.352Z" }, + { url = "https://files.pythonhosted.org/packages/7c/5a/455b53f11527568100ba6d5847635430645bad62d676f0bae4173fc85c90/fastar-0.9.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:f2f399fffb74bcd9e9d4507e253ace2430b5ccf61000596bda41e90414bcf4f2", size = 885257, upload-time = "2026-03-20T14:24:28.86Z" }, + { url = "https://files.pythonhosted.org/packages/4f/dd/0a8ea7b910293b07f8c82ef4e6451262ccf2a6f2020e880f184dc4abd6c2/fastar-0.9.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:87006c8770dfc558aefe927590bbcdaf9648ca4472a9ee6d10dfb7c0bda4ce5b", size = 968135, upload-time = "2026-03-20T14:25:45.614Z" }, + { url = "https://files.pythonhosted.org/packages/6b/cb/5c7e9231d6ba00e225623947068db09ddd4e401800b0afaf39eece14bfee/fastar-0.9.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:4d012644421d669d9746157193f4eafd371e8ae56ff7aef97612a4922418664c", size = 1034940, upload-time = "2026-03-20T14:25:58.893Z" }, + { url = "https://files.pythonhosted.org/packages/b5/b4/eccfcf7fe9d2a0cea6d71630acc48a762404058c9b3ae1323f74abcda005/fastar-0.9.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:094fd03b2e41b20a2602d340e2b52ad10051d82caa1263411cf247c1b1bc139f", size = 1073807, upload-time = "2026-03-20T14:26:11.694Z" }, + { url = "https://files.pythonhosted.org/packages/8b/53/6ddda28545b428d54c42f341d797046467c689616a36eae9a43ba56f2545/fastar-0.9.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:59bc500d7b6bdaf2ffb2b632bc6b0f97ddfb3bb7d31b54d61ceb00b5698d6484", size = 1025314, upload-time = "2026-03-20T14:26:24.624Z" }, + { url = "https://files.pythonhosted.org/packages/03/cf/71e2a67b0a69971044ad57fe7d196287ac32ab710bfc47f34745bb4a7834/fastar-0.9.0-cp312-cp312-win32.whl", hash = "sha256:25a1fd512ce23eb5aaab514742e7c6120244c211c349b86af068c3ae35792ec3", size = 452740, upload-time = "2026-03-20T14:26:56.604Z" }, + { url = "https://files.pythonhosted.org/packages/c0/c5/0ffa2fffac0d80d2283db577ff23f8d91886010ea858c657f8278c2a222c/fastar-0.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:b10a409797d01ee4062547e95e4a89f6bb52677b144076fd5a1f9d28d463ab10", size = 485282, upload-time = "2026-03-20T14:26:44.926Z" }, + { url = "https://files.pythonhosted.org/packages/14/20/999d72dc12e793a6c7889176fc42ad917d568d802c91b4126629e9be45a9/fastar-0.9.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea4d98fc62990986ce00d2021f08ff2aa6eae71636415c5a5f65f3a6a657dc5e", size = 461795, upload-time = "2026-03-20T14:26:36.728Z" }, + { url = "https://files.pythonhosted.org/packages/9a/26/ea9339facfe4ee224be673c6888dbf077f28b0f81185f80353966c9f4925/fastar-0.9.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7b55ae4a3a481fd90a63ac558a7e8aab652ac1dfd15d8657266e71bf65346408", size = 706740, upload-time = "2026-03-20T14:25:33.741Z" }, + { url = "https://files.pythonhosted.org/packages/77/52/f3b06867e5ca8d5b2c1c15a1563415e0037b5831f2058ee72b03960296d9/fastar-0.9.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f07c6bdeedfeb30ef459f21fa9ab06e2b6727f7e7653176d3abb7a85f447c400", size = 627615, upload-time = "2026-03-20T14:25:21.608Z" }, + { url = "https://files.pythonhosted.org/packages/52/32/021b0a633bca18bca4f831392c2938c15c4605de2d9895b783ad6d64679c/fastar-0.9.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:90f46492e05141089766699e95c79d470e8013192fbbb16ef16b576281f3b8ee", size = 864584, upload-time = "2026-03-20T14:24:56.941Z" }, + { url = "https://files.pythonhosted.org/packages/3f/54/e2e1b4c8512d670373047e5e585b1d1ff9ffd722b0a17647d22c9c9bd248/fastar-0.9.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:108bb46c080ca152bb331f1e0576177d36e9badba51b1d5724d2823542e0dd1f", size = 760246, upload-time = "2026-03-20T14:23:51.964Z" }, + { url = "https://files.pythonhosted.org/packages/fa/7d/1e283dd8dbb3647049594bb477bdc053045c6fff2d3f06386d2dcacce7aa/fastar-0.9.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d17d311cfbb559154ba940972b6d07a3a7ac221a2a01208f119ad03495f01d32", size = 757024, upload-time = "2026-03-20T14:24:04.69Z" }, + { url = "https://files.pythonhosted.org/packages/87/ac/82d3cb64d318ce16c5d1a26a40b8aa570fcc9b23684221aece838c4cbada/fastar-0.9.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d2ef34e7088f308e73460e1b8d9b0479a743f679816782a80db6ae87ee68714a", size = 921630, upload-time = "2026-03-20T14:24:18.155Z" }, + { url = "https://files.pythonhosted.org/packages/f7/b8/3e7892f1a25a1a2054a20de6c846c0794b8fa361e5b9d3d00915b41e97bd/fastar-0.9.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c93bf4732d0dd6adae4a8b3bbebe19af76ee1072b7688bf39c5a1d120425a772", size = 815791, upload-time = "2026-03-20T14:24:43.28Z" }, + { url = "https://files.pythonhosted.org/packages/db/5e/8fcc662db1fd0985f4f8a54e79276416565a0d1fcb8da66665b2061ead30/fastar-0.9.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a67b061b1099cf3b8b6234dd3605fa16f5078ab6b51c8d77ad7a5d11c3cf834", size = 818980, upload-time = "2026-03-20T14:25:09.545Z" }, + { url = "https://files.pythonhosted.org/packages/68/ed/37291fbd6c9b5b0905712da6191bdfc25a7dc236efbf130e3a1a7d1b9440/fastar-0.9.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:912efe3121dc1f3c05940cfa1c6b09b8868d702d24566506aa1d0d96e429923a", size = 884578, upload-time = "2026-03-20T14:24:30.584Z" }, + { url = "https://files.pythonhosted.org/packages/94/19/7b3b7af978ae4f012664781554716d67549ab19ddbcb6e6d1adc04d7a5e7/fastar-0.9.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2394980cc126a3263e115600bc4ff9e7320cddde83c99fc334ab530be5b7166e", size = 967790, upload-time = "2026-03-20T14:25:46.975Z" }, + { url = "https://files.pythonhosted.org/packages/e6/38/4cce2a8e529a7d3e99e427c9bbcccd7013ff6b3ba295613e6f1c573c9e6c/fastar-0.9.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:d0aff74ea98642784c941d3cd8c35943258d4b9626157858901c5b181683339b", size = 1033892, upload-time = "2026-03-20T14:26:00.22Z" }, + { url = "https://files.pythonhosted.org/packages/1a/3f/86f25d79b1b369c2756ee338b76d1696a9cac3a737e819459b0ad7822ede/fastar-0.9.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:3e8a1deaf490f4ec15eca7e66127ff89cdefd20217f358739d4b7b1cb322f663", size = 1072969, upload-time = "2026-03-20T14:26:13.089Z" }, + { url = "https://files.pythonhosted.org/packages/10/4f/6ec0c123c15bbcb9a9b82e979dc81273789ebbfbb4a2b41a1a6941577c94/fastar-0.9.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c9bd8879ebf05aa247e60e454bb7568cbdd44f016b8c58e31e5398039403e61d", size = 1025768, upload-time = "2026-03-20T14:26:25.957Z" }, + { url = "https://files.pythonhosted.org/packages/5a/d1/cbdcdb78ca034ed51a9f53c2650885873d8b06727452c1cc33f56ad0c66a/fastar-0.9.0-cp313-cp313-win32.whl", hash = "sha256:11b35e6453a2da8715dd8415b3999ea57805125493e44ce41a32404bf9a510a7", size = 452742, upload-time = "2026-03-20T14:26:58.014Z" }, + { url = "https://files.pythonhosted.org/packages/74/ee/138d2f8e3504232a279afa224d3e5922c15dc7126613e6c135cfc8e10ec9/fastar-0.9.0-cp313-cp313-win_amd64.whl", hash = "sha256:10a1e7f7bfa1c6f03e4c657fdc0a32ebe42d8e48f681403dc0c67258e1cb5bef", size = 484917, upload-time = "2026-03-20T14:26:46.135Z" }, + { url = "https://files.pythonhosted.org/packages/db/ca/f518ee9dccc45097560a2cff245590c65b7b348171c8d2f2e487cf92a69f/fastar-0.9.0-cp313-cp313-win_arm64.whl", hash = "sha256:e5484ac1415e0ca8bc7b69231e3e3afb52887fed10b839ca676767635a13f06f", size = 461202, upload-time = "2026-03-20T14:26:37.937Z" }, + { url = "https://files.pythonhosted.org/packages/cf/00/99700dd33273c118d7d9ab7ad5db6650b430448d4cfae62aec6ef6ca4cb7/fastar-0.9.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:ccb2289f24ee6555330eb77149486d3a2ec8926450a96157dd20c636a0eec085", size = 707059, upload-time = "2026-03-20T14:25:35.086Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a4/4808dcfa8dddb9d7f50d830a39a9084d9d148ed06fcac8b040620848bc24/fastar-0.9.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2bfee749a46666785151b33980aef8f916e6e0341c3d241bde4d3de6be23f00c", size = 627135, upload-time = "2026-03-20T14:25:23.134Z" }, + { url = "https://files.pythonhosted.org/packages/da/cb/9c92e97d760d769846cae6ce53332a5f2a9246eb07b369ac2a4ebf10480c/fastar-0.9.0-cp314-cp314-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f6096ec3f216a21fa9ac430ce509447f56c5bd979170c4c0c3b4f3cb2051c1a8", size = 864974, upload-time = "2026-03-20T14:24:58.624Z" }, + { url = "https://files.pythonhosted.org/packages/84/38/9dadebd0b7408b4f415827db35169bbd0741e726e38e3afd3e491b589c61/fastar-0.9.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7a806e54d429f7f57e35dc709e801da8c0ba9095deb7331d6574c05ae4537ea", size = 760262, upload-time = "2026-03-20T14:23:53.275Z" }, + { url = "https://files.pythonhosted.org/packages/d6/7d/7afc5721429515aa0873b268513f656f905d27ff1ca54d875af6be9e9bc6/fastar-0.9.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f9a06abf8c7f74643a75003334683eb6e94fabef05f60449b7841eeb093a47b0", size = 757575, upload-time = "2026-03-20T14:24:06.143Z" }, + { url = "https://files.pythonhosted.org/packages/fc/5d/7498842c62bd6057553aa598cd175a0db41fdfeda7bdfde48dab63ffb285/fastar-0.9.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e9b5c155946f20ce3f999fb1362ed102876156ad6539e1b73a921f14efb758c", size = 924827, upload-time = "2026-03-20T14:24:19.364Z" }, + { url = "https://files.pythonhosted.org/packages/69/ab/13322e98fe1a00ed6efbfa5bf06fcfff8a6979804ef7fcef884b5e0c6f85/fastar-0.9.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbdedac6a84ef9ebc1cee6d777599ad51c9e98ceb8ebb386159483dcd60d0e16", size = 816536, upload-time = "2026-03-20T14:24:44.844Z" }, + { url = "https://files.pythonhosted.org/packages/fe/fd/0aa5b9994c8dba75b73a9527be4178423cb926db9f7eca562559e27ccdfd/fastar-0.9.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51df60a2f7af09f75b2a4438b25cb903d8774e24c492acf2bca8b0863026f34c", size = 818686, upload-time = "2026-03-20T14:25:10.799Z" }, + { url = "https://files.pythonhosted.org/packages/46/d6/e000cd49ef85c11a8350e461e6c48a4345ace94fb52242ac8c1d5dad1dfc/fastar-0.9.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:15016d0da7dbc664f09145fc7db549ba8fe32628c6e44e20926655b82de10658", size = 885043, upload-time = "2026-03-20T14:24:32.231Z" }, + { url = "https://files.pythonhosted.org/packages/68/28/ee734fe273475b9b25554370d92a21fc809376cf79aa072de29d23c17518/fastar-0.9.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c66a8e1f7dae6357be8c1f83ce6330febbc08e49fc40a5a2e91061e7867bbcbf", size = 967965, upload-time = "2026-03-20T14:25:48.397Z" }, + { url = "https://files.pythonhosted.org/packages/c1/35/165b3a75f1ee8045af9478c8aae5b5e20913cca2d4a5adb1be445e8d015a/fastar-0.9.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:1c6829be3f55d2978cb62921ef4d7c3dd58fe68ee994f81d49bd0a3c5240c977", size = 1034507, upload-time = "2026-03-20T14:26:01.518Z" }, + { url = "https://files.pythonhosted.org/packages/ba/4e/4097b5015da02484468c16543db2f8dec2fe827d321a798acbd9068e0f13/fastar-0.9.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:68db849e01d49543f31d56ef2fe15527afe2b9e0fb21794edc4d772553d83407", size = 1073388, upload-time = "2026-03-20T14:26:14.448Z" }, + { url = "https://files.pythonhosted.org/packages/07/d7/3b86af4e63a551398763a1bbbbac91e1c0754ece7ac7157218b33a065f4c/fastar-0.9.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5569510407c0ded580cfeec99e46ebe85ce27e199e020c5c1ea6f570e302c946", size = 1025190, upload-time = "2026-03-20T14:26:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/39/07/8c50a60f03e095053306fcf57d9d99343bce0e99d5b758bf96de31aec849/fastar-0.9.0-cp314-cp314-win32.whl", hash = "sha256:3f7be0a34ffbead52ab5f4a1e445e488bf39736acb006298d3b3c5b4f2c5915e", size = 452301, upload-time = "2026-03-20T14:26:59.234Z" }, + { url = "https://files.pythonhosted.org/packages/ee/69/aa6d67b09485ba031408296d6ff844c7d83cdcb9f8fcc240422c6f83be87/fastar-0.9.0-cp314-cp314-win_amd64.whl", hash = "sha256:cf7f68b98ed34ce628994c9bbd4f56cf6b4b175b3f7b8cbe35c884c8efec0a5b", size = 484948, upload-time = "2026-03-20T14:26:48.45Z" }, + { url = "https://files.pythonhosted.org/packages/20/6d/dba29d87ca929f95a5a7025c7d30720ad8478beed29fff482f29e1e8b045/fastar-0.9.0-cp314-cp314-win_arm64.whl", hash = "sha256:155dae97aca4b245eabb25e23fd16bfd42a0447f9db7f7789ab1299b02d94487", size = 461170, upload-time = "2026-03-20T14:26:39.191Z" }, + { url = "https://files.pythonhosted.org/packages/96/8f/c3ea0adac50a8037987ee7f15ff94767ebb604faf6008cbd2b8efa46c372/fastar-0.9.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:a63df018232623e136178953031057c7ac0dbf0acc6f0e8c1dc7dbc19e64c22f", size = 705857, upload-time = "2026-03-20T14:25:36.842Z" }, + { url = "https://files.pythonhosted.org/packages/ae/b3/e0e1aad1778065559680a73cdf982ed07b04300c2e5bf778dec8668eda6f/fastar-0.9.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6fb44f8675ef87087cb08f9bf4dfa15e818571a5f567ff692f3ea007cff867b5", size = 626210, upload-time = "2026-03-20T14:25:24.361Z" }, + { url = "https://files.pythonhosted.org/packages/94/f3/3c117335cbea26b3bc05382c27e6028278ed048d610b8de427c68f2fec84/fastar-0.9.0-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:81092daa991d0f095424e0e28ed589e03c81a21eeddc9b981184ddda5869bf9d", size = 864879, upload-time = "2026-03-20T14:25:00.131Z" }, + { url = "https://files.pythonhosted.org/packages/26/5d/e8d00ec3b2692d14ea111ddae25bf10e0cb60d5d79915c3d8ea393a87d5c/fastar-0.9.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e8793e2618d0d6d5a7762d6007371f57f02544364864e40e6b9d304b0f151b2", size = 759117, upload-time = "2026-03-20T14:23:54.826Z" }, + { url = "https://files.pythonhosted.org/packages/1a/61/6e080fdbc28c72dded8b6ff396035d6dc292f9b1c67b8797ac2372ca5733/fastar-0.9.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:83f7ef7056791fc95b6afa987238368c9a73ad0edcedc6bc80076f9fbd3a2a78", size = 756527, upload-time = "2026-03-20T14:24:07.494Z" }, + { url = "https://files.pythonhosted.org/packages/e8/97/2cf1a07884d171c028bd4ae5ecf7ded6f31581f79ab26711dcdad0a3d5ab/fastar-0.9.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3a456230fcc0e560823f5d04ae8e4c867300d8ee710b14ddcdd1b316ac3dd8d", size = 921763, upload-time = "2026-03-20T14:24:20.787Z" }, + { url = "https://files.pythonhosted.org/packages/f6/e3/c1d698a45f9f5dc892ed7d64badc9c38f1e5c1667048191969c438d2b428/fastar-0.9.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a60b117ebadc46c10c87852d2158a4d6489adbfbbec37be036b4cfbeca07b449", size = 815493, upload-time = "2026-03-20T14:24:46.482Z" }, + { url = "https://files.pythonhosted.org/packages/25/38/e124a404043fba75a8cb2f755ca49e4f01e18400bb6607a5f76526e07164/fastar-0.9.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a6199b4ca0c092a7ae47f5f387492d46a0a2d82cb3b7aa0bf50d7f7d5d8d57f", size = 819166, upload-time = "2026-03-20T14:25:12.027Z" }, + { url = "https://files.pythonhosted.org/packages/85/4a/5b1ea5c8d0dbdfcec2fd1e6a243d6bb5a1c7cd55e132cc532eb8b1cbd6d9/fastar-0.9.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:34efe114caf10b4d5ea404069ff1f6cc0e55a708c7091059b0fc087f65c0a331", size = 883618, upload-time = "2026-03-20T14:24:33.552Z" }, + { url = "https://files.pythonhosted.org/packages/d3/0b/ae46e5722a67a3c2e0ff83d539b0907d6e5092f6395840c0eb6ede81c5d6/fastar-0.9.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:4d44c1f8d9c5a3e4e58e6ffb77f4ca023ba9d9ddd88e7c613b3419a8feaa3db7", size = 966294, upload-time = "2026-03-20T14:25:50.024Z" }, + { url = "https://files.pythonhosted.org/packages/98/58/b161cf8711f4a50a3e57b6f89bc703c1aed282cad50434b3bc8524738b20/fastar-0.9.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:d2af970a1f773965b05f1765017a417380ad080ea49590516eb25b23c039158a", size = 1033177, upload-time = "2026-03-20T14:26:02.868Z" }, + { url = "https://files.pythonhosted.org/packages/e2/76/faac7292bce9b30106a6b6a9f5ddb658fdb03abe2644688b82023c8f76b9/fastar-0.9.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:1675346d7cbdde0d21869c3b597be19b5e31a36442bdf3a48d83a49765b269dc", size = 1073620, upload-time = "2026-03-20T14:26:16.121Z" }, + { url = "https://files.pythonhosted.org/packages/b8/be/dd55ffcc302d6f0ff4aba1616a0da3edc8fcefb757869cad81de74604a35/fastar-0.9.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dc440daa28591aeb4d387c171e824f179ad2ab256ce7a315472395b8d5f80392", size = 1025147, upload-time = "2026-03-20T14:26:28.767Z" }, + { url = "https://files.pythonhosted.org/packages/4b/c7/080bbb2b3c4e739fe6486fd765a09905f6c16c1068b2fcf2bb51a5e83937/fastar-0.9.0-cp314-cp314t-win32.whl", hash = "sha256:32787880600a988d11547628034993ef948499ae4514a30509817242c4eb98b1", size = 452317, upload-time = "2026-03-20T14:27:03.243Z" }, + { url = "https://files.pythonhosted.org/packages/42/39/00553739a7e9e35f78a0c5911d181acf6b6e132337adc9bbc3575f5f6f04/fastar-0.9.0-cp314-cp314t-win_amd64.whl", hash = "sha256:92fa18ec4958f33473259980685d29248ac44c96eed34026ad7550f93dd9ee23", size = 483994, upload-time = "2026-03-20T14:26:52.76Z" }, + { url = "https://files.pythonhosted.org/packages/4f/36/a7af08d233624515d9a0f5d41b7a01a51fd825b8c795e41800215a3200e7/fastar-0.9.0-cp314-cp314t-win_arm64.whl", hash = "sha256:34f646ac4f5bed3661a106ca56c1744e7146a02aacf517d47b24fd3f25dc1ff6", size = 460604, upload-time = "2026-03-20T14:26:40.771Z" }, + { url = "https://files.pythonhosted.org/packages/69/9f/4aeaa0a1ac2aca142a276ea136e651e94ba1341bd840ba455ed250d1970b/fastar-0.9.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b74ce299066288f3b90221dca8507f59c7d9e8df91387948006b9a0fea4f9bdc", size = 710738, upload-time = "2026-03-20T14:25:41.17Z" }, + { url = "https://files.pythonhosted.org/packages/d0/19/9f8fb5c0e803254c5d535c362102dd604d9bdb206d5a36150f4637cadf09/fastar-0.9.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:76be31936cabce31cbb6381128f851cf0a6da2d5c25357615cd1504b26dc31cf", size = 633000, upload-time = "2026-03-20T14:25:28.496Z" }, + { url = "https://files.pythonhosted.org/packages/ef/8d/0d1d9a87a78f1e686bb6c7c69688a4c9ad1efb65e49cc66310b97fdf900b/fastar-0.9.0-pp311-pypy311_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c4c9ea0e0d69445b0ca3b0bd80bd8237fec8a914275b0472ecca2b555c12f3a3", size = 871226, upload-time = "2026-03-20T14:25:04.351Z" }, + { url = "https://files.pythonhosted.org/packages/ef/04/366937320b1cca522570c527a45b1254bd68d057e68956baefc49eacae27/fastar-0.9.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b665c33afcd1d581b82235b690d999c5446ccc2c4d80c4a95f30df3b43d22494", size = 763872, upload-time = "2026-03-20T14:23:59.122Z" }, + { url = "https://files.pythonhosted.org/packages/c8/f2/121c5432bb152da68fc466a0d0206d66383a40a2f9beff5583d9277aceee/fastar-0.9.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d2a9a49f9217f4f60f9ba23fdd1f7f3f04fed97391145eb9460ec83ca0b4bd33", size = 762897, upload-time = "2026-03-20T14:24:11.932Z" }, + { url = "https://files.pythonhosted.org/packages/80/9e/88d3a603b997063e032f94cc0fff74031d76903f38cc30416a400395df03/fastar-0.9.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59d860e82a531e9cc67e7f500a299bffbe6e93d80bbf48401fd8f452a0c58f28", size = 927024, upload-time = "2026-03-20T14:24:24.689Z" }, + { url = "https://files.pythonhosted.org/packages/a6/17/d6dc778c45b0c7d9a279706d7a5d62122dab0a7a0cb39aac6f5ef42f13f6/fastar-0.9.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3feede2d72ec0782b5ccc18568f36cbe33816be396551aa47b3e1b73c322cdd2", size = 821265, upload-time = "2026-03-20T14:24:50.407Z" }, + { url = "https://files.pythonhosted.org/packages/e0/e0/cec25d43df7ea4b4e3e875352c6d51c848c855792ba276c546732a7170af/fastar-0.9.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9ac410d32cbb514e966c45f0fedd0f9447b0dea9e734af714648da503603df6", size = 824024, upload-time = "2026-03-20T14:25:16.142Z" }, + { url = "https://files.pythonhosted.org/packages/52/90/c354969770d21d1b07c9281b5e23052392c288d22984a1917d30940e86cb/fastar-0.9.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:40b8c08df809e5e58d1839ccb37bafe4485deb6ee56bb7c5f0cbb72d701eb965", size = 888886, upload-time = "2026-03-20T14:24:38.229Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ac/eb2a01ed94e79b72003840448d2b69644a54a47f615c7d693432a1337caa/fastar-0.9.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:d62a4fd86eda3bea7cc32efd64d43b6d0fcdbbec009558b750fc362f20142789", size = 972503, upload-time = "2026-03-20T14:25:54.207Z" }, + { url = "https://files.pythonhosted.org/packages/8d/88/f7e28100fa7ff4a26a3493ad7a5d45d70f6de858c05f5c34aca3570c5839/fastar-0.9.0-pp311-pypy311_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:7bf6958bb6f94e5ec522e4a255b8e940d3561ad973f0be5dde6115b5a0854af5", size = 1039106, upload-time = "2026-03-20T14:26:07.686Z" }, + { url = "https://files.pythonhosted.org/packages/c0/de/52c578180fdaaf0f3289de8a878f1ac070f7e3e18a0689d3fd44dd7dae2c/fastar-0.9.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:c210b839c0a33cf8d08270963ad237bcb63029dddf6d6025333f7e5ca63930bd", size = 1080754, upload-time = "2026-03-20T14:26:20.299Z" }, + { url = "https://files.pythonhosted.org/packages/a4/45/1ea024be428ad9d89e9f738c9379507e97df9f9ed97e50e4a1d10ff90fef/fastar-0.9.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:fad70e257daefb42bab68dcd68beaf2e2a99da056d65f2c9f988449a4e869306", size = 1031304, upload-time = "2026-03-20T14:26:33.294Z" }, ] [[package]] @@ -3330,87 +3303,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/16/5c/d3f1733665f7cd582ef0842fb1d2ed0bc1fba10875160593342d22bba375/opentelemetry_util_http-0.60b1-py3-none-any.whl", hash = "sha256:66381ba28550c91bee14dcba8979ace443444af1ed609226634596b4b0faf199", size = 8947, upload-time = "2025-12-11T13:36:37.151Z" }, ] -[[package]] -name = "orjson" -version = "3.11.8" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/1b/2024d06792d0779f9dbc51531b61c24f76c75b9f4ce05e6f3377a1814cea/orjson-3.11.8.tar.gz", hash = "sha256:96163d9cdc5a202703e9ad1b9ae757d5f0ca62f4fa0cc93d1f27b0e180cc404e", size = 5603832, upload-time = "2026-03-31T16:16:27.878Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/90/5d81f61fe3e4270da80c71442864c091cee3003cc8984c75f413fe742a07/orjson-3.11.8-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e6693ff90018600c72fd18d3d22fa438be26076cd3c823da5f63f7bab28c11cb", size = 229663, upload-time = "2026-03-31T16:14:30.708Z" }, - { url = "https://files.pythonhosted.org/packages/6c/ef/85e06b0eb11de6fb424120fd5788a07035bd4c5e6bb7841ae9972a0526d1/orjson-3.11.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93de06bc920854552493c81f1f729fab7213b7db4b8195355db5fda02c7d1363", size = 132321, upload-time = "2026-03-31T16:14:32.317Z" }, - { url = "https://files.pythonhosted.org/packages/86/71/089338ee51b3132f050db0864a7df9bdd5e94c2a03820ab8a91e8f655618/orjson-3.11.8-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fe0b8c83e0f36247fc9431ce5425a5d95f9b3a689133d494831bdbd6f0bceb13", size = 130658, upload-time = "2026-03-31T16:14:33.935Z" }, - { url = "https://files.pythonhosted.org/packages/10/0d/f39d8802345d0ad65f7fd4374b29b9b59f98656dc30f21ca5c773265b2f0/orjson-3.11.8-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97d823831105c01f6c8029faf297633dbeb30271892bd430e9c24ceae3734744", size = 135708, upload-time = "2026-03-31T16:14:35.224Z" }, - { url = "https://files.pythonhosted.org/packages/ff/b5/40aae576b3473511696dcffea84fde638b2b64774eb4dcb8b2c262729f8a/orjson-3.11.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c60c0423f15abb6cf78f56dff00168a1b582f7a1c23f114036e2bfc697814d5f", size = 147047, upload-time = "2026-03-31T16:14:36.489Z" }, - { url = "https://files.pythonhosted.org/packages/7b/f0/778a84458d1fdaa634b2e572e51ce0b354232f580b2327e1f00a8d88c38c/orjson-3.11.8-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:01928d0476b216ad2201823b0a74000440360cef4fed1912d297b8d84718f277", size = 133072, upload-time = "2026-03-31T16:14:37.715Z" }, - { url = "https://files.pythonhosted.org/packages/bf/d3/1bbf2fc3ffcc4b829ade554b574af68cec898c9b5ad6420a923c75a073d3/orjson-3.11.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a4a639049c44d36a6d1ae0f4a94b271605c745aee5647fa8ffaabcdc01b69a6", size = 133867, upload-time = "2026-03-31T16:14:39.356Z" }, - { url = "https://files.pythonhosted.org/packages/08/94/6413da22edc99a69a8d0c2e83bf42973b8aa94d83ef52a6d39ac85da00bc/orjson-3.11.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3222adff1e1ff0dce93c16146b93063a7793de6c43d52309ae321234cdaf0f4d", size = 142268, upload-time = "2026-03-31T16:14:40.972Z" }, - { url = "https://files.pythonhosted.org/packages/4a/5f/aa5dbaa6136d7ba55f5461ac2e885efc6e6349424a428927fd46d68f4396/orjson-3.11.8-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:3223665349bbfb68da234acd9846955b1a0808cbe5520ff634bf253a4407009b", size = 424008, upload-time = "2026-03-31T16:14:42.637Z" }, - { url = "https://files.pythonhosted.org/packages/fa/aa/2c1962d108c7fe5e27aa03a354b378caf56d8eafdef15fd83dec081ce45a/orjson-3.11.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:61c9d357a59465736022d5d9ba06687afb7611dfb581a9d2129b77a6fcf78e59", size = 147942, upload-time = "2026-03-31T16:14:44.256Z" }, - { url = "https://files.pythonhosted.org/packages/47/d1/65f404f4c47eb1b0b4476f03ec838cac0c4aa933920ff81e5dda4dee14e7/orjson-3.11.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:58fb9b17b4472c7b1dcf1a54583629e62e23779b2331052f09a9249edf81675b", size = 136640, upload-time = "2026-03-31T16:14:45.884Z" }, - { url = "https://files.pythonhosted.org/packages/90/5f/7b784aea98bdb125a2f2da7c27d6c2d2f6d943d96ef0278bae596d563f85/orjson-3.11.8-cp310-cp310-win32.whl", hash = "sha256:b43dc2a391981d36c42fa57747a49dae793ef1d2e43898b197925b5534abd10a", size = 132066, upload-time = "2026-03-31T16:14:47.397Z" }, - { url = "https://files.pythonhosted.org/packages/92/ec/2e284af8d6c9478df5ef938917743f61d68f4c70d17f1b6e82f7e3b8dba1/orjson-3.11.8-cp310-cp310-win_amd64.whl", hash = "sha256:c98121237fea2f679480765abd566f7713185897f35c9e6c2add7e3a9900eb61", size = 127609, upload-time = "2026-03-31T16:14:48.78Z" }, - { url = "https://files.pythonhosted.org/packages/67/41/5aa7fa3b0f4dc6b47dcafc3cea909299c37e40e9972feabc8b6a74e2730d/orjson-3.11.8-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:003646067cc48b7fcab2ae0c562491c9b5d2cbd43f1e5f16d98fd118c5522d34", size = 229229, upload-time = "2026-03-31T16:14:50.424Z" }, - { url = "https://files.pythonhosted.org/packages/0a/d7/57e7f2458e0a2c41694f39fc830030a13053a84f837a5b73423dca1f0938/orjson-3.11.8-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:ed193ce51d77a3830cad399a529cd4ef029968761f43ddc549e1bc62b40d88f8", size = 128871, upload-time = "2026-03-31T16:14:51.888Z" }, - { url = "https://files.pythonhosted.org/packages/53/4a/e0fdb9430983e6c46e0299559275025075568aad5d21dd606faee3703924/orjson-3.11.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30491bc4f862aa15744b9738517454f1e46e56c972a2be87d70d727d5b2a8f8", size = 132104, upload-time = "2026-03-31T16:14:53.142Z" }, - { url = "https://files.pythonhosted.org/packages/08/4a/2025a60ff3f5c8522060cda46612d9b1efa653de66ed2908591d8d82f22d/orjson-3.11.8-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eda5b8b6be91d3f26efb7dc6e5e68ee805bc5617f65a328587b35255f138bf4", size = 130483, upload-time = "2026-03-31T16:14:54.605Z" }, - { url = "https://files.pythonhosted.org/packages/2d/3c/b9cde05bdc7b2385c66014e0620627da638d3d04e4954416ab48c31196c5/orjson-3.11.8-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee8db7bfb6fe03581bbab54d7c4124a6dd6a7f4273a38f7267197890f094675f", size = 135481, upload-time = "2026-03-31T16:14:55.901Z" }, - { url = "https://files.pythonhosted.org/packages/ff/f2/a8238e7734de7cb589fed319857a8025d509c89dc52fdcc88f39c6d03d5a/orjson-3.11.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d8b5231de76c528a46b57010bbd83fb51e056aa0220a372fd5065e978406f1c", size = 146819, upload-time = "2026-03-31T16:14:57.548Z" }, - { url = "https://files.pythonhosted.org/packages/db/10/dbf1e2a3cafea673b1b4350e371877b759060d6018a998643b7040e5de48/orjson-3.11.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:58a4a208a6fbfdb7a7327b8f201c6014f189f721fd55d047cafc4157af1bc62a", size = 132846, upload-time = "2026-03-31T16:14:58.91Z" }, - { url = "https://files.pythonhosted.org/packages/f8/fc/55e667ec9c85694038fcff00573d221b085d50777368ee3d77f38668bf3c/orjson-3.11.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f8952d6d2505c003e8f0224ff7858d341fa4e33fef82b91c4ff0ef070f2393c", size = 133580, upload-time = "2026-03-31T16:15:00.519Z" }, - { url = "https://files.pythonhosted.org/packages/7e/a6/c08c589a9aad0cb46c4831d17de212a2b6901f9d976814321ff8e69e8785/orjson-3.11.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0022bb50f90da04b009ce32c512dc1885910daa7cb10b7b0cba4505b16db82a8", size = 142042, upload-time = "2026-03-31T16:15:01.906Z" }, - { url = "https://files.pythonhosted.org/packages/5c/cc/2f78ea241d52b717d2efc38878615fe80425bf2beb6e68c984dde257a766/orjson-3.11.8-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ff51f9d657d1afb6f410cb435792ce4e1fe427aab23d2fcd727a2876e21d4cb6", size = 423845, upload-time = "2026-03-31T16:15:03.703Z" }, - { url = "https://files.pythonhosted.org/packages/70/07/c17dcf05dd8045457538428a983bf1f1127928df5bf328cb24d2b7cddacb/orjson-3.11.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6dbe9a97bdb4d8d9d5367b52a7c32549bba70b2739c58ef74a6964a6d05ae054", size = 147729, upload-time = "2026-03-31T16:15:05.203Z" }, - { url = "https://files.pythonhosted.org/packages/90/6c/0fb6e8a24e682e0958d71711ae6f39110e4b9cd8cab1357e2a89cb8e1951/orjson-3.11.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5c370674ebabe16c6ccac33ff80c62bf8a6e59439f5e9d40c1f5ab8fd2215b7", size = 136425, upload-time = "2026-03-31T16:15:07.052Z" }, - { url = "https://files.pythonhosted.org/packages/b2/35/4d3cc3a3d616035beb51b24a09bb872942dc452cf2df0c1d11ab35046d9f/orjson-3.11.8-cp311-cp311-win32.whl", hash = "sha256:0e32f7154299f42ae66f13488963269e5eccb8d588a65bc839ed986919fc9fac", size = 131870, upload-time = "2026-03-31T16:15:08.678Z" }, - { url = "https://files.pythonhosted.org/packages/13/26/9fe70f81d16b702f8c3a775e8731b50ad91d22dacd14c7599b60a0941cd1/orjson-3.11.8-cp311-cp311-win_amd64.whl", hash = "sha256:25e0c672a2e32348d2eb33057b41e754091f2835f87222e4675b796b92264f06", size = 127440, upload-time = "2026-03-31T16:15:09.994Z" }, - { url = "https://files.pythonhosted.org/packages/e8/c6/b038339f4145efd2859c1ca53097a52c0bb9cbdd24f947ebe146da1ad067/orjson-3.11.8-cp311-cp311-win_arm64.whl", hash = "sha256:9185589c1f2a944c17e26c9925dcdbc2df061cc4a145395c57f0c51f9b5dbfcd", size = 127399, upload-time = "2026-03-31T16:15:11.412Z" }, - { url = "https://files.pythonhosted.org/packages/01/f6/8d58b32ab32d9215973a1688aebd098252ee8af1766c0e4e36e7831f0295/orjson-3.11.8-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1cd0b77e77c95758f8e1100139844e99f3ccc87e71e6fc8e1c027e55807c549f", size = 229233, upload-time = "2026-03-31T16:15:12.762Z" }, - { url = "https://files.pythonhosted.org/packages/a9/8b/2ffe35e71f6b92622e8ea4607bf33ecf7dfb51b3619dcfabfd36cbe2d0a5/orjson-3.11.8-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:6a3d159d5ffa0e3961f353c4b036540996bf8b9697ccc38261c0eac1fd3347a6", size = 128772, upload-time = "2026-03-31T16:15:14.237Z" }, - { url = "https://files.pythonhosted.org/packages/27/d2/1f8682ae50d5c6897a563cb96bc106da8c9cb5b7b6e81a52e4cc086679b9/orjson-3.11.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76070a76e9c5ae661e2d9848f216980d8d533e0f8143e6ed462807b242e3c5e8", size = 131946, upload-time = "2026-03-31T16:15:15.607Z" }, - { url = "https://files.pythonhosted.org/packages/52/4b/5500f76f0eece84226e0689cb48dcde081104c2fa6e2483d17ca13685ffb/orjson-3.11.8-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:54153d21520a71a4c82a0dbb4523e468941d549d221dc173de0f019678cf3813", size = 130368, upload-time = "2026-03-31T16:15:17.066Z" }, - { url = "https://files.pythonhosted.org/packages/da/4e/58b927e08fbe9840e6c920d9e299b051ea667463b1f39a56e668669f8508/orjson-3.11.8-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:469ac2125611b7c5741a0b3798cd9e5786cbad6345f9f400c77212be89563bec", size = 135540, upload-time = "2026-03-31T16:15:18.404Z" }, - { url = "https://files.pythonhosted.org/packages/56/7c/ba7cb871cba1bcd5cd02ee34f98d894c6cea96353ad87466e5aef2429c60/orjson-3.11.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14778ffd0f6896aa613951a7fbf4690229aa7a543cb2bfbe9f358e08aafa9546", size = 146877, upload-time = "2026-03-31T16:15:19.833Z" }, - { url = "https://files.pythonhosted.org/packages/0b/5d/eb9c25fc1386696c6a342cd361c306452c75e0b55e86ad602dd4827a7fd7/orjson-3.11.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea56a955056a6d6c550cf18b3348656a9d9a4f02e2d0c02cabf3c73f1055d506", size = 132837, upload-time = "2026-03-31T16:15:21.282Z" }, - { url = "https://files.pythonhosted.org/packages/37/87/5ddeb7fc1fbd9004aeccab08426f34c81a5b4c25c7061281862b015fce2b/orjson-3.11.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53a0f57e59a530d18a142f4d4ba6dfc708dc5fdedce45e98ff06b44930a2a48f", size = 133624, upload-time = "2026-03-31T16:15:22.641Z" }, - { url = "https://files.pythonhosted.org/packages/22/09/90048793db94ee4b2fcec4ac8e5ddb077367637d6650be896b3494b79bb7/orjson-3.11.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b48e274f8824567d74e2158199e269597edf00823a1b12b63d48462bbf5123e", size = 141904, upload-time = "2026-03-31T16:15:24.435Z" }, - { url = "https://files.pythonhosted.org/packages/c0/cf/eb284847487821a5d415e54149a6449ba9bfc5872ce63ab7be41b8ec401c/orjson-3.11.8-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3f262401086a3960586af06c054609365e98407151f5ea24a62893a40d80dbbb", size = 423742, upload-time = "2026-03-31T16:15:26.155Z" }, - { url = "https://files.pythonhosted.org/packages/44/09/e12423d327071c851c13e76936f144a96adacfc037394dec35ac3fc8d1e8/orjson-3.11.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8e8c6218b614badf8e229b697865df4301afa74b791b6c9ade01d19a9953a942", size = 147806, upload-time = "2026-03-31T16:15:27.909Z" }, - { url = "https://files.pythonhosted.org/packages/b3/6d/37c2589ba864e582ffe7611643314785c6afb1f83c701654ef05daa8fcc7/orjson-3.11.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:093d489fa039ddade2db541097dbb484999fcc65fc2b0ff9819141e2ab364f25", size = 136485, upload-time = "2026-03-31T16:15:29.749Z" }, - { url = "https://files.pythonhosted.org/packages/be/c9/135194a02ab76b04ed9a10f68624b7ebd238bbe55548878b11ff15a0f352/orjson-3.11.8-cp312-cp312-win32.whl", hash = "sha256:e0950ed1bcb9893f4293fd5c5a7ee10934fbf82c4101c70be360db23ce24b7d2", size = 131966, upload-time = "2026-03-31T16:15:31.687Z" }, - { url = "https://files.pythonhosted.org/packages/ed/9a/9796f8fbe3cf30ce9cb696748dbb535e5c87be4bf4fe2e9ca498ef1fa8cf/orjson-3.11.8-cp312-cp312-win_amd64.whl", hash = "sha256:3cf17c141617b88ced4536b2135c552490f07799f6ad565948ea07bef0dcb9a6", size = 127441, upload-time = "2026-03-31T16:15:33.333Z" }, - { url = "https://files.pythonhosted.org/packages/cc/47/5aaf54524a7a4a0dd09dd778f3fa65dd2108290615b652e23d944152bc8e/orjson-3.11.8-cp312-cp312-win_arm64.whl", hash = "sha256:48854463b0572cc87dac7d981aa72ed8bf6deedc0511853dc76b8bbd5482d36d", size = 127364, upload-time = "2026-03-31T16:15:34.748Z" }, - { url = "https://files.pythonhosted.org/packages/66/7f/95fba509bb2305fab0073558f1e8c3a2ec4b2afe58ed9fcb7d3b8beafe94/orjson-3.11.8-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:3f23426851d98478c8970da5991f84784a76682213cd50eb73a1da56b95239dc", size = 229180, upload-time = "2026-03-31T16:15:36.426Z" }, - { url = "https://files.pythonhosted.org/packages/f6/9d/b237215c743ca073697d759b5503abd2cb8a0d7b9c9e21f524bcf176ab66/orjson-3.11.8-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:ebaed4cef74a045b83e23537b52ef19a367c7e3f536751e355a2a394f8648559", size = 128754, upload-time = "2026-03-31T16:15:38.049Z" }, - { url = "https://files.pythonhosted.org/packages/42/3d/27d65b6d11e63f133781425f132807aef793ed25075fec686fc8e46dd528/orjson-3.11.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97c8f5d3b62380b70c36ffacb2a356b7c6becec86099b177f73851ba095ef623", size = 131877, upload-time = "2026-03-31T16:15:39.484Z" }, - { url = "https://files.pythonhosted.org/packages/dd/cc/faee30cd8f00421999e40ef0eba7332e3a625ce91a58200a2f52c7fef235/orjson-3.11.8-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:436c4922968a619fb7fef1ccd4b8b3a76c13b67d607073914d675026e911a65c", size = 130361, upload-time = "2026-03-31T16:15:41.274Z" }, - { url = "https://files.pythonhosted.org/packages/5c/bb/a6c55896197f97b6d4b4e7c7fd77e7235517c34f5d6ad5aadd43c54c6d7c/orjson-3.11.8-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ab359aff0436d80bfe8a23b46b5fea69f1e18aaf1760a709b4787f1318b317f", size = 135521, upload-time = "2026-03-31T16:15:42.758Z" }, - { url = "https://files.pythonhosted.org/packages/9c/7c/ca3a3525aa32ff636ebb1778e77e3587b016ab2edb1b618b36ba96f8f2c0/orjson-3.11.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f89b6d0b3a8d81e1929d3ab3d92bbc225688bd80a770c49432543928fe09ac55", size = 146862, upload-time = "2026-03-31T16:15:44.341Z" }, - { url = "https://files.pythonhosted.org/packages/3c/0c/18a9d7f18b5edd37344d1fd5be17e94dc652c67826ab749c6e5948a78112/orjson-3.11.8-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29c009e7a2ca9ad0ed1376ce20dd692146a5d9fe4310848904b6b4fee5c5c137", size = 132847, upload-time = "2026-03-31T16:15:46.368Z" }, - { url = "https://files.pythonhosted.org/packages/23/91/7e722f352ad67ca573cee44de2a58fb810d0f4eb4e33276c6a557979fd8a/orjson-3.11.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:705b895b781b3e395c067129d8551655642dfe9437273211d5404e87ac752b53", size = 133637, upload-time = "2026-03-31T16:15:48.123Z" }, - { url = "https://files.pythonhosted.org/packages/af/04/32845ce13ac5bd1046ddb02ac9432ba856cc35f6d74dde95864fe0ad5523/orjson-3.11.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:88006eda83858a9fdf73985ce3804e885c2befb2f506c9a3723cdeb5a2880e3e", size = 141906, upload-time = "2026-03-31T16:15:49.626Z" }, - { url = "https://files.pythonhosted.org/packages/02/5e/c551387ddf2d7106d9039369862245c85738b828844d13b99ccb8d61fd06/orjson-3.11.8-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:55120759e61309af7fcf9e961c6f6af3dde5921cdb3ee863ef63fd9db126cae6", size = 423722, upload-time = "2026-03-31T16:15:51.176Z" }, - { url = "https://files.pythonhosted.org/packages/00/a3/ecfe62434096f8a794d4976728cb59bcfc4a643977f21c2040545d37eb4c/orjson-3.11.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:98bdc6cb889d19bed01de46e67574a2eab61f5cc6b768ed50e8ac68e9d6ffab6", size = 147801, upload-time = "2026-03-31T16:15:52.939Z" }, - { url = "https://files.pythonhosted.org/packages/18/6d/0dce10b9f6643fdc59d99333871a38fa5a769d8e2fc34a18e5d2bfdee900/orjson-3.11.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:708c95f925a43ab9f34625e45dcdadf09ec8a6e7b664a938f2f8d5650f6c090b", size = 136460, upload-time = "2026-03-31T16:15:54.431Z" }, - { url = "https://files.pythonhosted.org/packages/01/d6/6dde4f31842d87099238f1f07b459d24edc1a774d20687187443ab044191/orjson-3.11.8-cp313-cp313-win32.whl", hash = "sha256:01c4e5a6695dc09098f2e6468a251bc4671c50922d4d745aff1a0a33a0cf5b8d", size = 131956, upload-time = "2026-03-31T16:15:56.081Z" }, - { url = "https://files.pythonhosted.org/packages/c1/f9/4e494a56e013db957fb77186b818b916d4695b8fa2aa612364974160e91b/orjson-3.11.8-cp313-cp313-win_amd64.whl", hash = "sha256:c154a35dd1330707450bb4d4e7dd1f17fa6f42267a40c1e8a1daa5e13719b4b8", size = 127410, upload-time = "2026-03-31T16:15:57.54Z" }, - { url = "https://files.pythonhosted.org/packages/57/7f/803203d00d6edb6e9e7eef421d4e1adbb5ea973e40b3533f3cfd9aeb374e/orjson-3.11.8-cp313-cp313-win_arm64.whl", hash = "sha256:4861bde57f4d253ab041e374f44023460e60e71efaa121f3c5f0ed457c3a701e", size = 127338, upload-time = "2026-03-31T16:15:59.106Z" }, - { url = "https://files.pythonhosted.org/packages/6d/35/b01910c3d6b85dc882442afe5060cbf719c7d1fc85749294beda23d17873/orjson-3.11.8-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ec795530a73c269a55130498842aaa762e4a939f6ce481a7e986eeaa790e9da4", size = 229171, upload-time = "2026-03-31T16:16:00.651Z" }, - { url = "https://files.pythonhosted.org/packages/c2/56/c9ec97bd11240abef39b9e5d99a15462809c45f677420fd148a6c5e6295e/orjson-3.11.8-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c492a0e011c0f9066e9ceaa896fbc5b068c54d365fea5f3444b697ee01bc8625", size = 128746, upload-time = "2026-03-31T16:16:02.673Z" }, - { url = "https://files.pythonhosted.org/packages/3b/e4/66d4f30a90de45e2f0cbd9623588e8ae71eef7679dbe2ae954ed6d66a41f/orjson-3.11.8-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:883206d55b1bd5f5679ad5e6ddd3d1a5e3cac5190482927fdb8c78fb699193b5", size = 131867, upload-time = "2026-03-31T16:16:04.342Z" }, - { url = "https://files.pythonhosted.org/packages/19/30/2a645fc9286b928675e43fa2a3a16fb7b6764aa78cc719dc82141e00f30b/orjson-3.11.8-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5774c1fdcc98b2259800b683b19599c133baeb11d60033e2095fd9d4667b82db", size = 124664, upload-time = "2026-03-31T16:16:05.837Z" }, - { url = "https://files.pythonhosted.org/packages/db/44/77b9a86d84a28d52ba3316d77737f6514e17118119ade3f91b639e859029/orjson-3.11.8-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7381c83dd3d4a6347e6635950aa448f54e7b8406a27c7ecb4a37e9f1ae08b", size = 129701, upload-time = "2026-03-31T16:16:07.407Z" }, - { url = "https://files.pythonhosted.org/packages/b3/ea/eff3d9bfe47e9bc6969c9181c58d9f71237f923f9c86a2d2f490cd898c82/orjson-3.11.8-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14439063aebcb92401c11afc68ee4e407258d2752e62d748b6942dad20d2a70d", size = 141202, upload-time = "2026-03-31T16:16:09.48Z" }, - { url = "https://files.pythonhosted.org/packages/52/c8/90d4b4c60c84d62068d0cf9e4d8f0a4e05e76971d133ac0c60d818d4db20/orjson-3.11.8-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa72e71977bff96567b0f500fc5bfd2fdf915f34052c782a4c6ebbdaa97aa858", size = 127194, upload-time = "2026-03-31T16:16:11.02Z" }, - { url = "https://files.pythonhosted.org/packages/8d/c7/ea9e08d1f0ba981adffb629811148b44774d935171e7b3d780ae43c4c254/orjson-3.11.8-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7679bc2f01bb0d219758f1a5f87bb7c8a81c0a186824a393b366876b4948e14f", size = 133639, upload-time = "2026-03-31T16:16:13.434Z" }, - { url = "https://files.pythonhosted.org/packages/6c/8c/ddbbfd6ba59453c8fc7fe1d0e5983895864e264c37481b2a791db635f046/orjson-3.11.8-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:14f7b8fcb35ef403b42fa5ecfa4ed032332a91f3dc7368fbce4184d59e1eae0d", size = 141914, upload-time = "2026-03-31T16:16:14.955Z" }, - { url = "https://files.pythonhosted.org/packages/4e/31/dbfbefec9df060d34ef4962cd0afcb6fa7a9ec65884cb78f04a7859526c3/orjson-3.11.8-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:c2bdf7b2facc80b5e34f48a2d557727d5c5c57a8a450de122ae81fa26a81c1bc", size = 423800, upload-time = "2026-03-31T16:16:16.594Z" }, - { url = "https://files.pythonhosted.org/packages/87/cf/f74e9ae9803d4ab46b163494adba636c6d7ea955af5cc23b8aaa94cfd528/orjson-3.11.8-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ccd7ba1b0605813a0715171d39ec4c314cb97a9c85893c2c5c0c3a3729df38bf", size = 147837, upload-time = "2026-03-31T16:16:18.585Z" }, - { url = "https://files.pythonhosted.org/packages/64/e6/9214f017b5db85e84e68602792f742e5dc5249e963503d1b356bee611e01/orjson-3.11.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cdbc8c9c02463fef4d3c53a9ba3336d05496ec8e1f1c53326a1e4acc11f5c600", size = 136441, upload-time = "2026-03-31T16:16:20.151Z" }, - { url = "https://files.pythonhosted.org/packages/24/dd/3590348818f58f837a75fb969b04cdf187ae197e14d60b5e5a794a38b79d/orjson-3.11.8-cp314-cp314-win32.whl", hash = "sha256:0b57f67710a8cd459e4e54eb96d5f77f3624eba0c661ba19a525807e42eccade", size = 131983, upload-time = "2026-03-31T16:16:21.823Z" }, - { url = "https://files.pythonhosted.org/packages/3f/0f/b6cb692116e05d058f31ceee819c70f097fa9167c82f67fabe7516289abc/orjson-3.11.8-cp314-cp314-win_amd64.whl", hash = "sha256:735e2262363dcbe05c35e3a8869898022af78f89dde9e256924dc02e99fe69ca", size = 127396, upload-time = "2026-03-31T16:16:23.685Z" }, - { url = "https://files.pythonhosted.org/packages/c0/d1/facb5b5051fabb0ef9d26c6544d87ef19a939a9a001198655d0d891062dd/orjson-3.11.8-cp314-cp314-win_arm64.whl", hash = "sha256:6ccdea2c213cf9f3d9490cbd5d427693c870753df41e6cb375bd79bcbafc8817", size = 127330, upload-time = "2026-03-31T16:16:25.496Z" }, -] - [[package]] name = "outcome" version = "1.3.0.post0" @@ -5530,15 +5422,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/03/e09325cfc40a33a82b31ba1a3f1d97e85246736856a45a43b19fcb48b1c2/typer_slim-0.21.2-py3-none-any.whl", hash = "sha256:4705082bb6c66c090f60e47c8be09a93158c139ce0aa98df7c6c47e723395e5f", size = 56790, upload-time = "2026-02-10T19:33:47.221Z" }, ] -[[package]] -name = "types-orjson" -version = "3.6.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8c/97/3f78cfdf663e5668e8b490d8c84d6de089d2d8dbad935f0dc43555d52a90/types-orjson-3.6.2.tar.gz", hash = "sha256:cf9afcc79a86325c7aff251790338109ed6f6b1bab09d2d4262dd18c85a3c638", size = 1999, upload-time = "2022-01-07T11:31:10.518Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/55/84/b34abd2d08381c5113e475908a1d79d27dc9a15f669213cee4ca03d1a891/types_orjson-3.6.2-py3-none-any.whl", hash = "sha256:22ee9a79236b6b0bfb35a0684eded62ad930a88a56797fa3c449b026cf7dbfe4", size = 2224, upload-time = "2022-01-07T11:31:09.271Z" }, -] - [[package]] name = "types-protobuf" version = "6.32.1.20251210" @@ -5560,15 +5443,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1c/12/709ea261f2bf91ef0a26a9eed20f2623227a8ed85610c1e54c5805692ecb/types_requests-2.32.4.20260107-py3-none-any.whl", hash = "sha256:b703fe72f8ce5b31ef031264fe9395cac8f46a04661a79f7ed31a80fb308730d", size = 20676, upload-time = "2026-01-07T03:20:52.929Z" }, ] -[[package]] -name = "types-ujson" -version = "5.10.0.20250822" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5c/bd/d372d44534f84864a96c19a7059d9b4d29db8541828b8b9dc3040f7a46d0/types_ujson-5.10.0.20250822.tar.gz", hash = "sha256:0a795558e1f78532373cf3f03f35b1f08bc60d52d924187b97995ee3597ba006", size = 8437, upload-time = "2025-08-22T03:02:19.433Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d7/f2/d812543c350674d8b3f6e17c8922248ee3bb752c2a76f64beb8c538b40cf/types_ujson-5.10.0.20250822-py3-none-any.whl", hash = "sha256:3e9e73a6dc62ccc03449d9ac2c580cd1b7a8e4873220db498f7dd056754be080", size = 7657, upload-time = "2025-08-22T03:02:18.699Z" }, -] - [[package]] name = "typing-extensions" version = "4.15.0" @@ -5590,91 +5464,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, ] -[[package]] -name = "ujson" -version = "5.12.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cb/3e/c35530c5ffc25b71c59ae0cd7b8f99df37313daa162ce1e2f7925f7c2877/ujson-5.12.0.tar.gz", hash = "sha256:14b2e1eb528d77bc0f4c5bd1a7ebc05e02b5b41beefb7e8567c9675b8b13bcf4", size = 7158451, upload-time = "2026-03-11T22:19:30.397Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/db/ee/45c7c1f9268b0fecdd68f9ada490bc09632b74f5f90a9be759e51a746ddc/ujson-5.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:38051f36423f084b909aaadb3b41c9c6a2958e86956ba21a8489636911e87504", size = 56145, upload-time = "2026-03-11T22:17:49.409Z" }, - { url = "https://files.pythonhosted.org/packages/6d/dc/ed181dbfb2beee598e91280c6903ba71e10362b051716317e2d3664614bb/ujson-5.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:457fabc2700a8e6ddb85bc5a1d30d3345fe0d3ec3ee8161a4e032ec585801dfa", size = 53839, upload-time = "2026-03-11T22:17:50.973Z" }, - { url = "https://files.pythonhosted.org/packages/e4/d8/eb9ef42c660f431deeedc2e1b09c4ba29aa22818a439ddda7da6ae23ddfa/ujson-5.12.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57930ac9519099b852e190d2c04b1fb5d97ea128db33bce77ed874eccb4c7f09", size = 57844, upload-time = "2026-03-11T22:17:53.029Z" }, - { url = "https://files.pythonhosted.org/packages/68/37/0b586d079d3f2a5be5aa58ab5c423cbb4fae2ee4e65369c87aa74ac7e113/ujson-5.12.0-cp310-cp310-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:9b3b86ec3e818f3dd3e13a9de628e88a9990f4af68ecb0b12dd3de81227f0a26", size = 59923, upload-time = "2026-03-11T22:17:54.332Z" }, - { url = "https://files.pythonhosted.org/packages/28/ed/6a4b69eb397502767f438b5a2b4c066dccc9e3b263115f5ee07510250fc7/ujson-5.12.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:460e76a4daff214ae33ab959494962c93918cb44714ea3e3f748b14aa37f8a87", size = 57427, upload-time = "2026-03-11T22:17:55.317Z" }, - { url = "https://files.pythonhosted.org/packages/bb/4b/ae118440a72e85e68ee8dd26cfc47ea7857954a3341833cde9da7dc40ca3/ujson-5.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e584d0cdd37cac355aca52ed788d1a2d939d6837e2870d3b70e585db24025a50", size = 1037301, upload-time = "2026-03-11T22:17:56.427Z" }, - { url = "https://files.pythonhosted.org/packages/c2/76/834caa7905f65d3a695e4f5ff8d5d4a98508e396a9e8ab0739ab4fe2d422/ujson-5.12.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0fe9128e75c6aa6e9ae06c1408d6edd9179a2fef0fe6d9cda3166b887eba521d", size = 1196664, upload-time = "2026-03-11T22:17:58.061Z" }, - { url = "https://files.pythonhosted.org/packages/f2/33/1f3c1543c1d3f18c54bb3f8c1e74314fd6ad3c1aa375f01433e89a86bfa6/ujson-5.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3ed5cb149892141b1e77ef312924a327f2cc718b34247dae346ed66329e1b8be", size = 1089668, upload-time = "2026-03-11T22:17:59.617Z" }, - { url = "https://files.pythonhosted.org/packages/db/52/07d9da456a78296f61893b9d2bbfb2512f4233394748aae80b8d08c7d96e/ujson-5.12.0-cp310-cp310-win32.whl", hash = "sha256:973b7d7145b1ac553a7466a64afa8b31ec2693d7c7fff6a755059e0a2885dfd2", size = 39644, upload-time = "2026-03-11T22:18:01.212Z" }, - { url = "https://files.pythonhosted.org/packages/ec/e5/c1de3041672fa1ab97aae0f0b9f4e30a9b15d4104c734d5627779206c878/ujson-5.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:1d072a403d82aef8090c6d4f728e3a727dfdba1ad3b7fa3a052c3ecbd37e73cb", size = 43875, upload-time = "2026-03-11T22:18:02.268Z" }, - { url = "https://files.pythonhosted.org/packages/8b/49/714a9240d9e6bd86c9684a72f100a0005459165fb2b0f6bf1a1156be0b9f/ujson-5.12.0-cp310-cp310-win_arm64.whl", hash = "sha256:55ede2a7a051b3b7e71a394978a098d71b3783e6b904702ff45483fad434ae2d", size = 38563, upload-time = "2026-03-11T22:18:03.546Z" }, - { url = "https://files.pythonhosted.org/packages/10/22/fd22e2f6766bae934d3050517ca47d463016bd8688508d1ecc1baa18a7ad/ujson-5.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58a11cb49482f1a095a2bd9a1d81dd7c8fb5d2357f959ece85db4e46a825fd00", size = 56139, upload-time = "2026-03-11T22:18:04.591Z" }, - { url = "https://files.pythonhosted.org/packages/c6/fd/6839adff4fc0164cbcecafa2857ba08a6eaeedd7e098d6713cb899a91383/ujson-5.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9b3cf13facf6f77c283af0e1713e5e8c47a0fe295af81326cb3cb4380212e797", size = 53836, upload-time = "2026-03-11T22:18:05.662Z" }, - { url = "https://files.pythonhosted.org/packages/f9/b0/0c19faac62d68ceeffa83a08dc3d71b8462cf5064d0e7e0b15ba19898dad/ujson-5.12.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb94245a715b4d6e24689de12772b85329a1f9946cbf6187923a64ecdea39e65", size = 57851, upload-time = "2026-03-11T22:18:06.744Z" }, - { url = "https://files.pythonhosted.org/packages/04/f6/e7fd283788de73b86e99e08256726bb385923249c21dcd306e59d532a1a1/ujson-5.12.0-cp311-cp311-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:0fe6b8b8968e11dd9b2348bd508f0f57cf49ab3512064b36bc4117328218718e", size = 59906, upload-time = "2026-03-11T22:18:07.791Z" }, - { url = "https://files.pythonhosted.org/packages/d7/3a/b100735a2b43ee6e8fe4c883768e362f53576f964d4ea841991060aeaf35/ujson-5.12.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89e302abd3749f6d6699691747969a5d85f7c73081d5ed7e2624c7bd9721a2ab", size = 57409, upload-time = "2026-03-11T22:18:08.79Z" }, - { url = "https://files.pythonhosted.org/packages/5c/fa/f97cc20c99ca304662191b883ae13ae02912ca7244710016ba0cb8a5be34/ujson-5.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0727363b05ab05ee737a28f6200dc4078bce6b0508e10bd8aab507995a15df61", size = 1037339, upload-time = "2026-03-11T22:18:10.424Z" }, - { url = "https://files.pythonhosted.org/packages/10/7a/53ddeda0ffe1420db2f9999897b3cbb920fbcff1849d1f22b196d0f34785/ujson-5.12.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b62cb9a7501e1f5c9ffe190485501349c33e8862dde4377df774e40b8166871f", size = 1196625, upload-time = "2026-03-11T22:18:11.82Z" }, - { url = "https://files.pythonhosted.org/packages/0d/1a/4c64a6bef522e9baf195dd5be151bc815cd4896c50c6e2489599edcda85f/ujson-5.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a6ec5bf6bc361f2f0f9644907a36ce527715b488988a8df534120e5c34eeda94", size = 1089669, upload-time = "2026-03-11T22:18:13.343Z" }, - { url = "https://files.pythonhosted.org/packages/18/11/8ccb109f5777ec0d9fb826695a9e2ac36ae94c1949fc8b1e4d23a5bd067a/ujson-5.12.0-cp311-cp311-win32.whl", hash = "sha256:006428d3813b87477d72d306c40c09f898a41b968e57b15a7d88454ecc42a3fb", size = 39648, upload-time = "2026-03-11T22:18:14.785Z" }, - { url = "https://files.pythonhosted.org/packages/6f/e3/87fc4c27b20d5125cff7ce52d17ea7698b22b74426da0df238e3efcb0cf2/ujson-5.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:40aa43a7a3a8d2f05e79900858053d697a88a605e3887be178b43acbcd781161", size = 43876, upload-time = "2026-03-11T22:18:15.768Z" }, - { url = "https://files.pythonhosted.org/packages/9e/21/324f0548a8c8c48e3e222eaed15fb6d48c796593002b206b4a28a89e445f/ujson-5.12.0-cp311-cp311-win_arm64.whl", hash = "sha256:561f89cc82deeae82e37d4a4764184926fb432f740a9691563a391b13f7339a4", size = 38553, upload-time = "2026-03-11T22:18:17.251Z" }, - { url = "https://files.pythonhosted.org/packages/84/f6/ac763d2108d28f3a40bb3ae7d2fafab52ca31b36c2908a4ad02cd3ceba2a/ujson-5.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:09b4beff9cc91d445d5818632907b85fb06943b61cb346919ce202668bf6794a", size = 56326, upload-time = "2026-03-11T22:18:18.467Z" }, - { url = "https://files.pythonhosted.org/packages/25/46/d0b3af64dcdc549f9996521c8be6d860ac843a18a190ffc8affeb7259687/ujson-5.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ca0c7ce828bb76ab78b3991904b477c2fd0f711d7815c252d1ef28ff9450b052", size = 53910, upload-time = "2026-03-11T22:18:19.502Z" }, - { url = "https://files.pythonhosted.org/packages/9a/10/853c723bcabc3e9825a079019055fc99e71b85c6bae600607a2b9d31d18d/ujson-5.12.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2d79c6635ccffcbfc1d5c045874ba36b594589be81d50d43472570bb8de9c57", size = 57754, upload-time = "2026-03-11T22:18:20.874Z" }, - { url = "https://files.pythonhosted.org/packages/f9/c6/6e024830d988f521f144ead641981c1f7a82c17ad1927c22de3242565f5c/ujson-5.12.0-cp312-cp312-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:7e07f6f644d2c44d53b7a320a084eef98063651912c1b9449b5f45fcbdc6ccd2", size = 59936, upload-time = "2026-03-11T22:18:21.924Z" }, - { url = "https://files.pythonhosted.org/packages/34/c9/c5f236af5abe06b720b40b88819d00d10182d2247b1664e487b3ed9229cf/ujson-5.12.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:085b6ce182cdd6657481c7c4003a417e0655c4f6e58b76f26ee18f0ae21db827", size = 57463, upload-time = "2026-03-11T22:18:22.924Z" }, - { url = "https://files.pythonhosted.org/packages/ae/04/41342d9ef68e793a87d84e4531a150c2b682f3bcedfe59a7a5e3f73e9213/ujson-5.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:16b4fe9c97dc605f5e1887a9e1224287291e35c56cbc379f8aa44b6b7bcfe2bb", size = 1037239, upload-time = "2026-03-11T22:18:24.04Z" }, - { url = "https://files.pythonhosted.org/packages/d4/81/dc2b7617d5812670d4ff4a42f6dd77926430ee52df0dedb2aec7990b2034/ujson-5.12.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0d2e8db5ade3736a163906154ca686203acc7d1d30736cbf577c730d13653d84", size = 1196713, upload-time = "2026-03-11T22:18:25.391Z" }, - { url = "https://files.pythonhosted.org/packages/b6/9c/80acff0504f92459ed69e80a176286e32ca0147ac6a8252cd0659aad3227/ujson-5.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:93bc91fdadcf046da37a214eaa714574e7e9b1913568e93bb09527b2ceb7f759", size = 1089742, upload-time = "2026-03-11T22:18:26.738Z" }, - { url = "https://files.pythonhosted.org/packages/e3/f0/123ffaac17e45ef2b915e3e3303f8f4ea78bb8d42afad828844e08622b1e/ujson-5.12.0-cp312-cp312-win32.whl", hash = "sha256:2a248750abce1c76fbd11b2e1d88b95401e72819295c3b851ec73399d6849b3d", size = 39773, upload-time = "2026-03-11T22:18:28.244Z" }, - { url = "https://files.pythonhosted.org/packages/b5/20/f3bd2b069c242c2b22a69e033bfe224d1d15d3649e6cd7cc7085bb1412ff/ujson-5.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:1b5c6ceb65fecd28a1d20d1eba9dbfa992612b86594e4b6d47bb580d2dd6bcb3", size = 44040, upload-time = "2026-03-11T22:18:29.236Z" }, - { url = "https://files.pythonhosted.org/packages/f0/a7/01b5a0bcded14cd2522b218f2edc3533b0fcbccdea01f3e14a2b699071aa/ujson-5.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:9a5fcbe7b949f2e95c47ea8a80b410fcdf2da61c98553b45a4ee875580418b68", size = 38526, upload-time = "2026-03-11T22:18:30.551Z" }, - { url = "https://files.pythonhosted.org/packages/3f/f1/0ef0eeab1db8493e1833c8b440fe32cf7538f7afa6e7f7c7e9f62cef464d/ujson-5.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:15d416440148f3e56b9b244fdaf8a09fcf5a72e4944b8e119f5bf60417a2bfc8", size = 56331, upload-time = "2026-03-11T22:18:31.539Z" }, - { url = "https://files.pythonhosted.org/packages/b0/2f/9159f6f399b3f572d20847a2b80d133e3a03c14712b0da4971a36879fb64/ujson-5.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e0dd3676ea0837cd70ea1879765e9e9f6be063be0436de9b3ea4b775caf83654", size = 53910, upload-time = "2026-03-11T22:18:32.829Z" }, - { url = "https://files.pythonhosted.org/packages/e5/a9/f96376818d71495d1a4be19a0ab6acf0cc01dd8826553734c3d4dac685b2/ujson-5.12.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7bbf05c38debc90d1a195b11340cc85cb43ab3e753dc47558a3a84a38cbc72da", size = 57757, upload-time = "2026-03-11T22:18:33.866Z" }, - { url = "https://files.pythonhosted.org/packages/98/8d/dd4a151caac6fdcb77f024fbe7f09d465ebf347a628ed6dd581a0a7f6364/ujson-5.12.0-cp313-cp313-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:3c2f947e55d3c7cfe124dd4521ee481516f3007d13c6ad4bf6aeb722e190eb1b", size = 59940, upload-time = "2026-03-11T22:18:35.276Z" }, - { url = "https://files.pythonhosted.org/packages/c7/17/0d36c2fee0a8d8dc37b011ccd5bbdcfaff8b8ec2bcfc5be998661cdc935b/ujson-5.12.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ea6206043385343aff0b7da65cf73677f6f5e50de8f1c879e557f4298cac36a", size = 57465, upload-time = "2026-03-11T22:18:36.644Z" }, - { url = "https://files.pythonhosted.org/packages/8c/04/b0ee4a4b643a01ba398441da1e357480595edb37c6c94c508dbe0eb9eb60/ujson-5.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bb349dbba57c76eec25e5917e07f35aabaf0a33b9e67fc13d188002500106487", size = 1037236, upload-time = "2026-03-11T22:18:37.743Z" }, - { url = "https://files.pythonhosted.org/packages/2d/08/0e7780d0bbb48fe57ded91f550144bcc99c03b5360bf2886dd0dae0ea8f5/ujson-5.12.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:937794042342006f707837f38d721426b11b0774d327a2a45c0bd389eb750a87", size = 1196717, upload-time = "2026-03-11T22:18:39.101Z" }, - { url = "https://files.pythonhosted.org/packages/ba/4c/e0e34107715bb4dd2d4dcc1ce244d2f074638837adf38aff85a37506efe4/ujson-5.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6ad57654570464eb1b040b5c353dee442608e06cff9102b8fcb105565a44c9ed", size = 1089748, upload-time = "2026-03-11T22:18:40.473Z" }, - { url = "https://files.pythonhosted.org/packages/72/43/814f4e2b5374d0d505c254ba4bed43eb25d2d046f19f5fd88555f81a7bd0/ujson-5.12.0-cp313-cp313-win32.whl", hash = "sha256:76bf3e7406cf23a3e1ca6a23fb1fb9ea82f4f6bd226fe226e09146b0194f85dc", size = 39778, upload-time = "2026-03-11T22:18:41.791Z" }, - { url = "https://files.pythonhosted.org/packages/0f/fe/19310d848ebe93315b6cb171277e4ce29f47ef9d46caabd63ff05d5be548/ujson-5.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:15e555c4caca42411270b2ed2b2ebc7b3a42bb04138cef6c956e1f1d49709fe2", size = 44038, upload-time = "2026-03-11T22:18:43.094Z" }, - { url = "https://files.pythonhosted.org/packages/3f/e4/7a39103d7634691601a02bd1ca7268fba4da47ed586365e6ee68168f575a/ujson-5.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:bd03472c36fa3a386a6deb887113b9e3fa40efba8203eb4fe786d3c0ccc724f6", size = 38529, upload-time = "2026-03-11T22:18:44.167Z" }, - { url = "https://files.pythonhosted.org/packages/10/bd/9a8d693254bada62bfea75a507e014afcfdb6b9d047b6f8dd134bfefaf67/ujson-5.12.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:85833bca01aa5cae326ac759276dc175c5fa3f7b3733b7d543cf27f2df12d1ef", size = 56499, upload-time = "2026-03-11T22:18:45.431Z" }, - { url = "https://files.pythonhosted.org/packages/bd/2d/285a83df8176e18dcd675d1a4cff8f7620f003f30903ea43929406e98986/ujson-5.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d22cad98c2a10bbf6aa083a8980db6ed90d4285a841c4de892890c2b28286ef9", size = 53998, upload-time = "2026-03-11T22:18:47.184Z" }, - { url = "https://files.pythonhosted.org/packages/bf/8b/e2f09e16dabfa91f6a84555df34a4329fa7621e92ed054d170b9054b9bb2/ujson-5.12.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99cc80facad240b0c2fb5a633044420878aac87a8e7c348b9486450cba93f27c", size = 57783, upload-time = "2026-03-11T22:18:48.271Z" }, - { url = "https://files.pythonhosted.org/packages/68/fb/ba1d06f3658a0c36d0ab3869ec3914f202bad0a9bde92654e41516c7bb13/ujson-5.12.0-cp314-cp314-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:d1831c07bd4dce53c4b666fa846c7eba4b7c414f2e641a4585b7f50b72f502dc", size = 60011, upload-time = "2026-03-11T22:18:49.284Z" }, - { url = "https://files.pythonhosted.org/packages/64/2b/3e322bf82d926d9857206cd5820438d78392d1f523dacecb8bd899952f73/ujson-5.12.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e00cec383eab2406c9e006bd4edb55d284e94bb943fda558326048178d26961", size = 57465, upload-time = "2026-03-11T22:18:50.584Z" }, - { url = "https://files.pythonhosted.org/packages/e9/fd/af72d69603f9885e5136509a529a4f6d88bf652b457263ff96aefcd3ab7d/ujson-5.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f19b3af31d02a2e79c5f9a6deaab0fb3c116456aeb9277d11720ad433de6dfc6", size = 1037275, upload-time = "2026-03-11T22:18:51.998Z" }, - { url = "https://files.pythonhosted.org/packages/9c/a7/a2411ec81aef7872578e56304c3e41b3a544a9809e95c8e1df46923fc40b/ujson-5.12.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:bacbd3c69862478cbe1c7ed4325caedec580d8acf31b8ee1b9a1e02a56295cad", size = 1196758, upload-time = "2026-03-11T22:18:53.548Z" }, - { url = "https://files.pythonhosted.org/packages/ed/85/aa18ae175dd03a118555aa14304d4f466f9db61b924c97c6f84388ecacb1/ujson-5.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94c5f1621cbcab83c03be46441f090b68b9f307b6c7ec44d4e3f6d5997383df4", size = 1089760, upload-time = "2026-03-11T22:18:55.336Z" }, - { url = "https://files.pythonhosted.org/packages/d3/d4/4b40b67ac7e916ebffc3041ae2320c5c0b8a045300d4c542b6e50930cca5/ujson-5.12.0-cp314-cp314-win32.whl", hash = "sha256:e6369ac293d2cc40d52577e4fa3d75a70c1aae2d01fa3580a34a4e6eff9286b9", size = 41043, upload-time = "2026-03-11T22:18:56.505Z" }, - { url = "https://files.pythonhosted.org/packages/24/38/a1496d2a3428981f2b3a2ffbb4656c2b05be6cc406301d6b10a6445f6481/ujson-5.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:31348a0ffbfc815ce78daac569d893349d85a0b57e1cd2cdbba50b7f333784da", size = 45303, upload-time = "2026-03-11T22:18:57.454Z" }, - { url = "https://files.pythonhosted.org/packages/85/d3/39dbd3159543d9c57ec3a82d36226152cf0d710784894ce5aa24b8220ac1/ujson-5.12.0-cp314-cp314-win_arm64.whl", hash = "sha256:6879aed770557f0961b252648d36f6fdaab41079d37a2296b5649fd1b35608e0", size = 39860, upload-time = "2026-03-11T22:18:58.578Z" }, - { url = "https://files.pythonhosted.org/packages/c3/71/9b4dacb177d3509077e50497222d39eec04c8b41edb1471efc764d645237/ujson-5.12.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7ddb08b3c2f9213df1f2e3eb2fbea4963d80ec0f8de21f0b59898e34f3b3d96d", size = 56845, upload-time = "2026-03-11T22:18:59.629Z" }, - { url = "https://files.pythonhosted.org/packages/24/c2/8abffa3be1f3d605c4a62445fab232b3e7681512ce941c6b23014f404d36/ujson-5.12.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0a3ae28f0b209be5af50b54ca3e2123a3de3a57d87b75f1e5aa3d7961e041983", size = 54463, upload-time = "2026-03-11T22:19:00.697Z" }, - { url = "https://files.pythonhosted.org/packages/db/2e/60114a35d1d6796eb428f7affcba00a921831ff604a37d9142c3d8bbe5c5/ujson-5.12.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d30ad4359413c8821cc7b3707f7ca38aa8bc852ba3b9c5a759ee2d7740157315", size = 58689, upload-time = "2026-03-11T22:19:01.739Z" }, - { url = "https://files.pythonhosted.org/packages/c8/ad/010925c2116c21ce119f9c2ff18d01f48a19ade3ff4c5795da03ce5829fc/ujson-5.12.0-cp314-cp314t-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:02f93da7a4115e24f886b04fd56df1ee8741c2ce4ea491b7ab3152f744ad8f8e", size = 60618, upload-time = "2026-03-11T22:19:03.101Z" }, - { url = "https://files.pythonhosted.org/packages/9b/74/db7f638bf20282b1dccf454386cbd483faaaed3cdbb9cb27e06f74bb109e/ujson-5.12.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3ff4ede90ed771140caa7e1890de17431763a483c54b3c1f88bd30f0cc1affc0", size = 58151, upload-time = "2026-03-11T22:19:04.175Z" }, - { url = "https://files.pythonhosted.org/packages/9c/7e/3ebaecfa70a2e8ce623db8e21bd5cb05d42a5ef943bcbb3309d71b5de68d/ujson-5.12.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a7bf9cc97f05048ac8f3e02cd58f0fe62b901453c24345bfde287f4305dcc31c", size = 1038117, upload-time = "2026-03-11T22:19:05.558Z" }, - { url = "https://files.pythonhosted.org/packages/2e/aa/e073eda7f0036c2973b28db7bb99faba17a932e7b52d801f9bb3e726271f/ujson-5.12.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:2324d9a0502317ffc35d38e153c1b2fa9610ae03775c9d0f8d0cca7b8572b04e", size = 1197434, upload-time = "2026-03-11T22:19:06.92Z" }, - { url = "https://files.pythonhosted.org/packages/1c/01/b9a13f058fdd50c746b192c4447ca8d6352e696dcda912ccee10f032ff85/ujson-5.12.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:50524f4f6a1c839714dbaff5386a1afb245d2d5ec8213a01fbc99cea7307811e", size = 1090401, upload-time = "2026-03-11T22:19:08.383Z" }, - { url = "https://files.pythonhosted.org/packages/c4/37/3d1b4e0076b6e43379600b5229a5993db8a759ff2e1830ea635d876f6644/ujson-5.12.0-cp314-cp314t-win32.whl", hash = "sha256:f7a0430d765f9bda043e6aefaba5944d5f21ec43ff4774417d7e296f61917382", size = 41880, upload-time = "2026-03-11T22:19:09.671Z" }, - { url = "https://files.pythonhosted.org/packages/b1/c5/3c2a262a138b9f0014fe1134a6b5fdc2c54245030affbaac2fcbc0632138/ujson-5.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:ccbfd94e59aad4a2566c71912b55f0547ac1680bfac25eb138e6703eb3dd434e", size = 46365, upload-time = "2026-03-11T22:19:10.662Z" }, - { url = "https://files.pythonhosted.org/packages/83/40/956dc20b7e00dc0ff3259871864f18dab211837fce3478778bedb3132ac1/ujson-5.12.0-cp314-cp314t-win_arm64.whl", hash = "sha256:42d875388fbd091c7ea01edfff260f839ba303038ffb23475ef392012e4d63dd", size = 40398, upload-time = "2026-03-11T22:19:11.666Z" }, - { url = "https://files.pythonhosted.org/packages/95/3c/5ee154d505d1aad2debc4ba38b1a60ae1949b26cdb5fa070e85e320d6b64/ujson-5.12.0-graalpy312-graalpy250_312_native-macosx_10_13_x86_64.whl", hash = "sha256:bf85a00ac3b56a1e7a19c5be7b02b5180a0895ac4d3c234d717a55e86960691c", size = 54494, upload-time = "2026-03-11T22:19:13.035Z" }, - { url = "https://files.pythonhosted.org/packages/ce/b3/9496ec399ec921e434a93b340bd5052999030b7ac364be4cbe5365ac6b20/ujson-5.12.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:64df53eef4ac857eb5816a56e2885ccf0d7dff6333c94065c93b39c51063e01d", size = 57999, upload-time = "2026-03-11T22:19:14.385Z" }, - { url = "https://files.pythonhosted.org/packages/0e/da/e9ae98133336e7c0d50b43626c3f2327937cecfa354d844e02ac17379ed1/ujson-5.12.0-graalpy312-graalpy250_312_native-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6c0aed6a4439994c9666fb8a5b6c4eac94d4ef6ddc95f9b806a599ef83547e3b", size = 54518, upload-time = "2026-03-11T22:19:15.4Z" }, - { url = "https://files.pythonhosted.org/packages/58/10/978d89dded6bb1558cd46ba78f4351198bd2346db8a8ee1a94119022ce40/ujson-5.12.0-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efae5df7a8cc8bdb1037b0f786b044ce281081441df5418c3a0f0e1f86fe7bb3", size = 55736, upload-time = "2026-03-11T22:19:16.496Z" }, - { url = "https://files.pythonhosted.org/packages/80/25/1df8e6217c92e57a1266bf5be750b1dddc126ee96e53fe959d5693503bc6/ujson-5.12.0-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:8712b61eb1b74a4478cfd1c54f576056199e9f093659334aeb5c4a6b385338e5", size = 44615, upload-time = "2026-03-11T22:19:17.53Z" }, - { url = "https://files.pythonhosted.org/packages/19/fa/f4a957dddb99bd68c8be91928c0b6fefa7aa8aafc92c93f5d1e8b32f6702/ujson-5.12.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:871c0e5102e47995b0e37e8df7819a894a6c3da0d097545cd1f9f1f7d7079927", size = 52145, upload-time = "2026-03-11T22:19:18.566Z" }, - { url = "https://files.pythonhosted.org/packages/55/6e/50b5cf612de1ca06c7effdc5a5d7e815774dee85a5858f1882c425553b82/ujson-5.12.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:56ba3f7abbd6b0bb282a544dc38406d1a188d8bb9164f49fdb9c2fee62cb29da", size = 49577, upload-time = "2026-03-11T22:19:19.627Z" }, - { url = "https://files.pythonhosted.org/packages/6e/24/b6713fa9897774502cd4c2d6955bb4933349f7d84c3aa805531c382a4209/ujson-5.12.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c5a52987a990eb1bae55f9000994f1afdb0326c154fb089992f839ab3c30688", size = 50807, upload-time = "2026-03-11T22:19:20.778Z" }, - { url = "https://files.pythonhosted.org/packages/1f/b6/c0e0f7901180ef80d16f3a4bccb5dc8b01515a717336a62928963a07b80b/ujson-5.12.0-pp311-pypy311_pp73-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:adf28d13a33f9d750fe7a78fb481cac298fa257d8863d8727b2ea4455ea41235", size = 56972, upload-time = "2026-03-11T22:19:21.84Z" }, - { url = "https://files.pythonhosted.org/packages/02/a9/05d91b4295ea7239151eb08cf240e5a2ba969012fda50bc27bcb1ea9cd71/ujson-5.12.0-pp311-pypy311_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51acc750ec7a2df786cdc868fb16fa04abd6269a01d58cf59bafc57978773d8e", size = 52045, upload-time = "2026-03-11T22:19:22.879Z" }, - { url = "https://files.pythonhosted.org/packages/e3/7a/92047d32bf6f2d9db64605fc32e8eb0e0dd68b671eaafc12a464f69c4af4/ujson-5.12.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:ab9056d94e5db513d9313b34394f3a3b83e6301a581c28ad67773434f3faccab", size = 44053, upload-time = "2026-03-11T22:19:23.918Z" }, -] - [[package]] name = "uncalled-for" version = "0.2.0" From 13be6a3a0f12d3f36c286196ef555dd51dc09edb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 Apr 2026 11:42:31 +0000 Subject: [PATCH 62/69] =?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 f2d6af7a76..67b36e0e42 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Upgrades + +* ⬆️ Support free-threaded Python 3.14t. PR [#15149](https://github.com/fastapi/fastapi/pull/15149) by [@svlandeg](https://github.com/svlandeg). + ## 0.135.4 (2026-04-16) ### Refactors From 708606c982cf35718cb2214c0bb9261cf548f042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 16 Apr 2026 13:45:09 +0200 Subject: [PATCH 63/69] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.136.?= =?UTF-8?q?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 67b36e0e42..95db49b28c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.136.0 (2026-04-16) + ### Upgrades * ⬆️ Support free-threaded Python 3.14t. PR [#15149](https://github.com/fastapi/fastapi/pull/15149) by [@svlandeg](https://github.com/svlandeg). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 21cf17498d..73a1c20e99 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.135.4" +__version__ = "0.136.0" from starlette import status as status From 3f4169be1afaca39b0227e4947cf4e2596aa4e31 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Thu, 16 Apr 2026 14:21:03 +0200 Subject: [PATCH 64/69] =?UTF-8?q?=F0=9F=94=92=EF=B8=8F=20Add=20zizmor=20an?= =?UTF-8?q?d=20fix=20audit=20findings=20(#15316)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/dependabot.yml | 15 +++++++- .github/workflows/add-to-project.yml | 8 ++-- .github/workflows/build-docs.yml | 35 ++++++++++++------ .github/workflows/contributors.yml | 17 ++++++--- .github/workflows/deploy-docs.yml | 35 +++++++++--------- .github/workflows/detect-conflicts.yml | 6 ++- .github/workflows/issue-manager.yml | 11 +++--- .github/workflows/label-approved.yml | 14 ++++--- .github/workflows/labeler.yml | 8 ++-- .github/workflows/latest-changes.yml | 16 ++++---- .github/workflows/notify-translations.yml | 17 ++++++--- .github/workflows/people.yml | 17 ++++++--- .github/workflows/pre-commit.yml | 21 +++++++---- .github/workflows/publish.yml | 12 ++++-- .github/workflows/smokeshow.yml | 20 ++++++---- .github/workflows/sponsors.yml | 17 ++++++--- .github/workflows/test-redistribute.yml | 10 +++-- .github/workflows/test.yml | 45 +++++++++++++++-------- .github/workflows/topic-repos.yml | 13 +++++-- .github/workflows/translate.yml | 33 ++++++++++------- .pre-commit-config.yaml | 10 ++++- pyproject.toml | 1 + uv.lock | 20 ++++++++++ 23 files changed, 266 insertions(+), 135 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index fdca003877..918a98f511 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,12 +5,25 @@ updates: directory: "/" schedule: interval: "daily" + cooldown: + default-days: 7 commit-message: prefix: ⬆ # Python - package-ecosystem: "uv" directory: "/" schedule: - interval: "monthly" + interval: "daily" + cooldown: + default-days: 7 + commit-message: + prefix: ⬆ + # pre-commit + - package-ecosystem: "pre-commit" + directory: "/" + schedule: + interval: "daily" + cooldown: + default-days: 7 commit-message: prefix: ⬆ diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml index dccea83f35..01a0824449 100644 --- a/.github/workflows/add-to-project.yml +++ b/.github/workflows/add-to-project.yml @@ -1,18 +1,20 @@ name: Add to Project on: - pull_request_target: + pull_request_target: # zizmor: ignore[dangerous-triggers] issues: types: - opened - reopened +permissions: {} + jobs: add-to-project: name: Add to project runs-on: ubuntu-latest steps: - - uses: actions/add-to-project@v1.0.2 + - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 with: project-url: https://github.com/orgs/fastapi/projects/2 - github-token: ${{ secrets.PROJECTS_TOKEN }} + github-token: ${{ secrets.PROJECTS_TOKEN }} # zizmor: ignore[secrets-outside-env] diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index ea18fc0109..e25af8a87e 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -8,6 +8,8 @@ on: - opened - synchronize +permissions: {} + jobs: changes: runs-on: ubuntu-latest @@ -18,9 +20,11 @@ jobs: outputs: docs: ${{ steps.filter.outputs.docs }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false # For pull requests it's not necessary to checkout the code but for the main branch it is - - uses: dorny/paths-filter@v4 + - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 id: filter with: filters: | @@ -42,14 +46,17 @@ jobs: outputs: langs: ${{ steps.show-langs.outputs.langs }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -75,14 +82,17 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -91,13 +101,14 @@ jobs: run: uv sync --locked --no-dev --group docs - name: Update Languages run: uv run ./scripts/docs.py update-languages - - uses: actions/cache@v5 + - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: key: mkdocs-cards-${{ matrix.lang }}-${{ github.ref }} path: docs/${{ matrix.lang }}/.cache - name: Build Docs - run: uv run ./scripts/docs.py build-lang ${{ matrix.lang }} - - uses: actions/upload-artifact@v7 + run: | # zizmor: ignore[template-injection] - comes from trusted source + uv run ./scripts/docs.py build-lang ${{ matrix.lang }} + - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: docs-site-${{ matrix.lang }} path: ./site/** @@ -111,7 +122,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@release/v1 + uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 with: jobs: ${{ toJSON(needs) }} allowed-skips: build-docs diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index f3ced6aa30..785ecea939 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -10,6 +10,8 @@ on: required: false default: "false" +permissions: {} + jobs: job: if: github.repository_owner == 'fastapi' @@ -21,14 +23,17 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: true # Required for `git push` in `contributors.py` - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -37,13 +42,13 @@ jobs: run: uv sync --locked --no-dev --group github-actions # Allow debugging with tmate - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 + uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3.23 if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true env: - GITHUB_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} + GITHUB_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} # zizmor: ignore[secrets-outside-env] - name: FastAPI People Contributors run: uv run ./scripts/contributors.py env: - GITHUB_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} + GITHUB_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} # zizmor: ignore[secrets-outside-env] diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 3002120399..ead5ed4bce 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -1,37 +1,38 @@ name: Deploy Docs on: - workflow_run: + workflow_run: # zizmor: ignore[dangerous-triggers] workflows: - Build Docs types: - completed -permissions: - deployments: write - issues: write - pull-requests: write - statuses: write +permissions: {} jobs: deploy-docs: runs-on: ubuntu-latest + permissions: + deployments: write + issues: write + pull-requests: write + statuses: write steps: - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: - enable-cache: true - cache-dependency-glob: | - pyproject.toml - uv.lock + version: "0.11.4" + enable-cache: false - name: Install GitHub Actions dependencies run: uv sync --locked --no-dev --group github-actions - name: Deploy Docs Status Pending @@ -45,7 +46,7 @@ jobs: run: | rm -rf ./site mkdir ./site - - uses: actions/download-artifact@v8 + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: path: ./site/ pattern: docs-site-* @@ -59,10 +60,10 @@ jobs: env: PROJECT_NAME: fastapitiangolo BRANCH: ${{ ( github.event.workflow_run.head_repository.full_name == github.repository && github.event.workflow_run.head_branch == 'master' && 'main' ) || ( github.event.workflow_run.head_sha ) }} - uses: cloudflare/wrangler-action@v3 + uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3.14.1 with: - apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} - accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} # zizmor: ignore[secrets-outside-env] + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} # zizmor: ignore[secrets-outside-env] command: pages deploy ./site --project-name=${{ env.PROJECT_NAME }} --branch=${{ env.BRANCH }} - name: Deploy Docs Status Error if: failure() diff --git a/.github/workflows/detect-conflicts.yml b/.github/workflows/detect-conflicts.yml index aba329db85..38d526bd9b 100644 --- a/.github/workflows/detect-conflicts.yml +++ b/.github/workflows/detect-conflicts.yml @@ -1,9 +1,11 @@ name: "Conflict detector" on: push: - pull_request_target: + pull_request_target: # zizmor: ignore[dangerous-triggers] types: [synchronize] +permissions: {} + jobs: main: permissions: @@ -12,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check if PRs have merge conflicts - uses: eps1lon/actions-label-merge-conflict@v3 + uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3.0.3 with: dirtyLabel: "conflicts" repoToken: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/issue-manager.yml b/.github/workflows/issue-manager.yml index 2ae588da13..c0ffd7ac70 100644 --- a/.github/workflows/issue-manager.yml +++ b/.github/workflows/issue-manager.yml @@ -9,25 +9,26 @@ on: issues: types: - labeled - pull_request_target: + pull_request_target: # zizmor: ignore[dangerous-triggers] types: - labeled workflow_dispatch: -permissions: - issues: write - pull-requests: write +permissions: {} jobs: issue-manager: if: github.repository_owner == 'fastapi' runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write steps: - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: tiangolo/issue-manager@0.6.0 + - uses: tiangolo/issue-manager@2fb3484ec9279485df8659e8ec73de262431737d # 0.6.0 with: token: ${{ secrets.GITHUB_TOKEN }} config: > diff --git a/.github/workflows/label-approved.yml b/.github/workflows/label-approved.yml index 1307fb8c23..1f27809368 100644 --- a/.github/workflows/label-approved.yml +++ b/.github/workflows/label-approved.yml @@ -5,26 +5,30 @@ on: - cron: "0 12 * * *" workflow_dispatch: -permissions: - pull-requests: write +permissions: {} jobs: label-approved: if: github.repository_owner == 'fastapi' runs-on: ubuntu-latest + permissions: + pull-requests: write steps: - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" enable-cache: true cache-dependency-glob: | pyproject.toml diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 7aeb448e6f..58c6892375 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -1,6 +1,6 @@ name: Labels on: - pull_request_target: + pull_request_target: # zizmor: ignore[dangerous-triggers] types: - opened - synchronize @@ -9,6 +9,8 @@ on: - labeled - unlabeled +permissions: {} + jobs: labeler: permissions: @@ -16,7 +18,7 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@v6 + - uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1 if: ${{ github.event.action != 'labeled' && github.event.action != 'unlabeled' }} - run: echo "Done adding labels" # Run this after labeler applied labels @@ -27,7 +29,7 @@ jobs: pull-requests: read runs-on: ubuntu-latest steps: - - uses: docker://agilepathway/pull-request-label-checker:latest + - uses: agilepathway/label-checker@c3d16ad512e7cea5961df85ff2486bb774caf3c5 # v1.6.65 with: one_of: breaking,security,feature,bug,refactor,upgrade,docs,lang-all,internal repo_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index b9e45ea629..aaa12c17d5 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -1,7 +1,7 @@ name: Latest Changes on: - pull_request_target: + pull_request_target: # zizmor: ignore[dangerous-triggers] branches: - master types: @@ -16,27 +16,29 @@ on: required: false default: 'false' +permissions: {} + jobs: latest-changes: runs-on: ubuntu-latest + if: github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true steps: - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - # pin to actions/checkout@v5 for compatibility with latest-changes - # Ref: https://github.com/actions/checkout/issues/2313 - - uses: actions/checkout@v5 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # To allow latest-changes to commit to the main branch - token: ${{ secrets.FASTAPI_LATEST_CHANGES }} + token: ${{ secrets.FASTAPI_LATEST_CHANGES }} # zizmor: ignore[secrets-outside-env] + persist-credentials: true # required by tiangolo/latest-changes # Allow debugging with tmate - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 + uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3.23 if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true - - uses: tiangolo/latest-changes@0.4.1 + - uses: tiangolo/latest-changes@c9d329cb147f0ddf4fb631214e3f838ff17ccbbd # 0.4.1 with: token: ${{ secrets.GITHUB_TOKEN }} latest_changes_file: docs/en/docs/release-notes.md diff --git a/.github/workflows/notify-translations.yml b/.github/workflows/notify-translations.yml index 31f3eb4021..07d4e0bdfb 100644 --- a/.github/workflows/notify-translations.yml +++ b/.github/workflows/notify-translations.yml @@ -1,10 +1,12 @@ name: Notify Translations on: - pull_request_target: + pull_request_target: # zizmor: ignore[dangerous-triggers] types: - labeled - closed + branches: + - master workflow_dispatch: inputs: number: @@ -15,6 +17,8 @@ on: required: false default: 'false' +permissions: {} + jobs: job: runs-on: ubuntu-latest @@ -25,14 +29,17 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -41,7 +48,7 @@ jobs: run: uv sync --locked --no-dev --group github-actions # Allow debugging with tmate - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 + uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3.23 if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml index cb3b742788..51e2188cc4 100644 --- a/.github/workflows/people.yml +++ b/.github/workflows/people.yml @@ -10,6 +10,8 @@ on: required: false default: "false" +permissions: {} + jobs: job: if: github.repository_owner == 'fastapi' @@ -21,14 +23,17 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: true # Required for `git push` in `people.py` - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -37,14 +42,14 @@ jobs: run: uv sync --locked --no-dev --group github-actions # Allow debugging with tmate - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 + uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3.23 if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true env: - GITHUB_TOKEN: ${{ secrets.FASTAPI_PEOPLE }} + GITHUB_TOKEN: ${{ secrets.FASTAPI_PEOPLE }} # zizmor: ignore[secrets-outside-env] - name: FastAPI People Experts run: uv run ./scripts/people.py env: - GITHUB_TOKEN: ${{ secrets.FASTAPI_PEOPLE }} + GITHUB_TOKEN: ${{ secrets.FASTAPI_PEOPLE }} # zizmor: ignore[secrets-outside-env] SLEEP_INTERVAL: ${{ vars.PEOPLE_SLEEP_INTERVAL }} diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index f027140ed7..5b0be38011 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -6,6 +6,8 @@ on: - opened - synchronize +permissions: {} + env: # Forks and Dependabot don't have access to secrets HAS_SECRETS: ${{ secrets.PRE_COMMIT != '' }} @@ -18,7 +20,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v5 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 name: Checkout PR for own repo if: env.HAS_SECRETS == 'true' with: @@ -28,22 +30,25 @@ jobs: # And it needs the full history to be able to compute diffs fetch-depth: 0 # A token other than the default GITHUB_TOKEN is needed to be able to trigger CI - token: ${{ secrets.PRE_COMMIT }} + token: ${{ secrets.PRE_COMMIT }} # zizmor: ignore[secrets-outside-env] + persist-credentials: true # Required for `git push` command # pre-commit lite ci needs the default checkout configs to work - - uses: actions/checkout@v5 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 name: Checkout PR for fork if: env.HAS_SECRETS == 'false' with: # To be able to commit it needs the head branch of the PR, the remote one ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" cache-dependency-glob: | pyproject.toml uv.lock @@ -51,7 +56,7 @@ jobs: run: uv sync --locked --extra all - name: Run prek - pre-commit id: precommit - run: uvx prek run --from-ref origin/${GITHUB_BASE_REF} --to-ref HEAD --show-diff-on-failure + run: uv run prek run --from-ref origin/${GITHUB_BASE_REF} --to-ref HEAD --show-diff-on-failure continue-on-error: true - name: Commit and push changes if: env.HAS_SECRETS == 'true' @@ -65,7 +70,7 @@ jobs: git commit -m "🎨 Auto format" git push fi - - uses: pre-commit-ci/lite-action@v1.1.0 + - uses: pre-commit-ci/lite-action@5d6cc0eb514c891a40562a58a8e71576c5c7fb43 # v1.1.0 if: env.HAS_SECRETS == 'false' with: msg: 🎨 Auto format @@ -85,6 +90,6 @@ jobs: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@release/v1 + uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 with: jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 58f4f6dd8a..2695854dca 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -5,6 +5,8 @@ on: types: - created +permissions: {} + jobs: publish: runs-on: ubuntu-latest @@ -16,13 +18,17 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Install uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + with: + version: "0.11.4" - name: Build distribution run: uv build - name: Publish diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index 7e7cbc68bf..46f2610180 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -1,34 +1,38 @@ name: Smokeshow on: - workflow_run: + workflow_run: # zizmor: ignore[dangerous-triggers] workflows: [Test] types: [completed] -permissions: - statuses: write +permissions: {} jobs: smokeshow: runs-on: ubuntu-latest + permissions: + statuses: write steps: - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" cache-dependency-glob: | pyproject.toml uv.lock - run: uv sync --locked --no-dev --group github-actions - - uses: actions/download-artifact@v8 + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: coverage-html path: htmlcov @@ -51,4 +55,4 @@ jobs: SMOKESHOW_GITHUB_CONTEXT: coverage SMOKESHOW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SMOKESHOW_GITHUB_PR_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} - SMOKESHOW_AUTH_KEY: ${{ secrets.SMOKESHOW_AUTH_KEY }} + SMOKESHOW_AUTH_KEY: ${{ secrets.SMOKESHOW_AUTH_KEY }} # zizmor: ignore[secrets-outside-env] diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml index 88590ffa6c..ef72a68248 100644 --- a/.github/workflows/sponsors.yml +++ b/.github/workflows/sponsors.yml @@ -10,6 +10,8 @@ on: required: false default: "false" +permissions: {} + jobs: job: if: github.repository_owner == 'fastapi' @@ -21,14 +23,17 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: true # Required for `git push` in `sponsors.py` - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -37,12 +42,12 @@ jobs: run: uv sync --locked --no-dev --group github-actions # Allow debugging with tmate - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 + uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3.23 if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true - name: FastAPI People Sponsors run: uv run ./scripts/sponsors.py env: - SPONSORS_TOKEN: ${{ secrets.SPONSORS_TOKEN }} - PR_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} + SPONSORS_TOKEN: ${{ secrets.SPONSORS_TOKEN }} # zizmor: ignore[secrets-outside-env] + PR_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} # zizmor: ignore[secrets-outside-env] diff --git a/.github/workflows/test-redistribute.yml b/.github/workflows/test-redistribute.yml index ad9df4bf98..fad16fb2cd 100644 --- a/.github/workflows/test-redistribute.yml +++ b/.github/workflows/test-redistribute.yml @@ -9,6 +9,8 @@ on: - opened - synchronize +permissions: {} + jobs: test-redistribute: runs-on: ubuntu-latest @@ -17,9 +19,11 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Install build dependencies @@ -55,6 +59,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@release/v1 + uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 with: jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ed78f6e53f..87b1805e60 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,6 +12,8 @@ on: # cron every week on monday - cron: "0 0 * * 1" +permissions: {} + env: UV_NO_SYNC: true INLINE_SNAPSHOT_DEFAULT_FLAGS: review @@ -26,9 +28,11 @@ jobs: outputs: src: ${{ steps.filter.outputs.src }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false # For pull requests it's not necessary to checkout the code but for the main branch it is - - uses: dorny/paths-filter@v4 + - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 id: filter with: filters: | @@ -99,14 +103,17 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python-version }} - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -134,7 +141,7 @@ jobs: # Do not store coverage for all possible combinations to avoid file size max errors in Smokeshow - name: Store coverage files if: matrix.coverage == 'coverage' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: coverage-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.deprecated-tests}}-${{ hashFiles('**/coverage/.coverage.*') }} path: coverage @@ -153,14 +160,17 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.13" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -168,7 +178,7 @@ jobs: - name: Install Dependencies run: uv sync --no-dev --group tests --extra all - name: CodSpeed benchmarks - uses: CodSpeedHQ/action@v4 + uses: CodSpeedHQ/action@1c8ae4843586d3ba879736b7f6b7b0c990757fab # v4.12.1 with: mode: simulation run: uv run --no-sync pytest tests/benchmarks --codspeed @@ -182,13 +192,16 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -196,7 +209,7 @@ jobs: - name: Install Dependencies run: uv sync --locked --no-dev --group tests --extra all - name: Get coverage files - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: coverage-* path: coverage @@ -205,7 +218,7 @@ jobs: - run: uv run coverage combine coverage - run: uv run coverage html --title "Coverage for ${{ github.sha }}" - name: Store coverage HTML - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: coverage-html path: htmlcov @@ -225,7 +238,7 @@ jobs: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@release/v1 + uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 with: jobs: ${{ toJSON(needs) }} allowed-skips: coverage-combine,test,benchmark diff --git a/.github/workflows/topic-repos.yml b/.github/workflows/topic-repos.yml index 46f6d60847..0f40b7b3d6 100644 --- a/.github/workflows/topic-repos.yml +++ b/.github/workflows/topic-repos.yml @@ -5,6 +5,8 @@ on: - cron: "0 12 1 * *" workflow_dispatch: +permissions: {} + jobs: topic-repos: if: github.repository_owner == 'fastapi' @@ -16,14 +18,17 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: true # Required for `git push` in `topic_repos.py` - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -33,4 +38,4 @@ jobs: - name: Update Topic Repos run: uv run ./scripts/topic_repos.py env: - GITHUB_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} + GITHUB_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} # zizmor: ignore[secrets-outside-env] diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml index efa052c7a2..ed21881cd9 100644 --- a/.github/workflows/translate.yml +++ b/.github/workflows/translate.yml @@ -41,6 +41,8 @@ on: required: false default: 10 +permissions: {} + jobs: langs: runs-on: ubuntu-latest @@ -48,14 +50,17 @@ jobs: langs: ${{ steps.show-langs.outputs.langs }} commands: ${{ steps.show-langs.outputs.commands }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" cache-dependency-glob: | pyproject.toml uv.lock @@ -78,23 +83,23 @@ jobs: matrix: lang: ${{ fromJson(needs.langs.outputs.langs) }} command: ${{ fromJson(needs.langs.outputs.commands) }} - permissions: - contents: write steps: - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 with: + version: "0.11.4" cache-dependency-glob: | pyproject.toml uv.lock @@ -102,20 +107,20 @@ jobs: run: uv sync --locked --no-dev --group github-actions --group translations # Allow debugging with tmate - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 + uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3.23 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 }} + GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }} # zizmor: ignore[secrets-outside-env] + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} # zizmor: ignore[secrets-outside-env] - name: FastAPI Translate run: | - uv run ./scripts/translate.py ${{ matrix.command }} + uv run ./scripts/translate.py "$COMMAND" uv run ./scripts/translate.py make-pr env: - GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }} # zizmor: ignore[secrets-outside-env] + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} # zizmor: ignore[secrets-outside-env] LANGUAGE: ${{ matrix.lang }} EN_PATH: ${{ github.event.inputs.en_path }} COMMAND: ${{ matrix.command }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4eae7a64df..7913c813ac 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 + rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # v6.0.0 hooks: - id: check-added-large-files args: ['--maxkb=750'] @@ -85,3 +85,11 @@ repos: entry: uv run python scripts/add_latest_release_date.py files: ^docs/en/docs/release-notes\.md$ pass_filenames: false + + - id: zizmor + name: zizmor + language: python + entry: uv run zizmor . + files: ^\.github\/workflows\/ + require_serial: true + pass_filenames: false diff --git a/pyproject.toml b/pyproject.toml index 60530b6370..8d8c4978d8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -126,6 +126,7 @@ dev = [ { include-group = "translations" }, "playwright >=1.57.0", "prek >=0.2.22", + "zizmor >=1.23.1", ] docs = [ { include-group = "docs-tests" }, diff --git a/uv.lock b/uv.lock index a47632d5a0..92bb1fd4c8 100644 --- a/uv.lock +++ b/uv.lock @@ -1154,6 +1154,7 @@ dev = [ { name = "strawberry-graphql" }, { name = "ty" }, { name = "typer" }, + { name = "zizmor" }, ] docs = [ { name = "black" }, @@ -1296,6 +1297,7 @@ dev = [ { name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" }, { name = "ty", specifier = ">=0.0.9" }, { name = "typer", specifier = ">=0.21.1" }, + { name = "zizmor", specifier = ">=1.23.1" }, ] docs = [ { name = "black", specifier = ">=25.1.0" }, @@ -5997,3 +5999,21 @@ sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50e wheels = [ { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, ] + +[[package]] +name = "zizmor" +version = "1.23.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9e/58/d0228b1332f001f905d3cdd288a878d339e740ef8a92c321696a7359bdcd/zizmor-1.23.1.tar.gz", hash = "sha256:eb9871f1de004d8c6e35ff403bd6a41c495062736e78b9c4a98988970c598639", size = 463942, upload-time = "2026-03-08T16:57:29.065Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/57/32893d3370aa39f140934ee346a77aff1bc38d1de5248b9385dfcea612b7/zizmor-1.23.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:85f222eb610379aeeea76e4dc616621fdae9f21db77d1b006820452cafa739eb", size = 9085239, upload-time = "2026-03-08T16:57:32.241Z" }, + { url = "https://files.pythonhosted.org/packages/e3/43/037b68a2d173a44286f27c5c47e219d8beba758a323e1642770956831732/zizmor-1.23.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:82a7925bbdbc69713cbeb19ec90012cba3b92e3ace65ae60088e9604c5724182", size = 8657180, upload-time = "2026-03-08T16:57:23.078Z" }, + { url = "https://files.pythonhosted.org/packages/e5/37/322ec0e8b8d39a7de30290b754bd564c0b1c432d72f7b7aa011eca87cc7b/zizmor-1.23.1-py3-none-manylinux_2_24_aarch64.whl", hash = "sha256:19af913bb4bcd6dfeea41477fcf203d69e053f4b14a2b35690485c44ffa6c4a7", size = 8788247, upload-time = "2026-03-08T16:57:18.477Z" }, + { url = "https://files.pythonhosted.org/packages/3f/e7/5ca6f7d56741b190c6d7d3721eb98c66e23fb68d64e6886c92993e049f36/zizmor-1.23.1-py3-none-manylinux_2_28_armv7l.whl", hash = "sha256:08ae0d8f4d665f6cf9b475913c64d2193d52ffc6f02ce66d4dcfd1b92daf4f82", size = 8374212, upload-time = "2026-03-08T16:57:25.437Z" }, + { url = "https://files.pythonhosted.org/packages/d4/a5/a3784392aeaca14d65c5e5efa2795d887ba24db4871a942e06a99f90a3c8/zizmor-1.23.1-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:08233d0d25947e43ac92374f22383c04e43f351f44bc44d60b3c0695157c0f3e", size = 9230697, upload-time = "2026-03-08T16:57:34.425Z" }, + { url = "https://files.pythonhosted.org/packages/b6/0d/4475ded1664262af70525700e158c3156653391770159d65cd80245fb68e/zizmor-1.23.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:795e04dff47ca1d1b0af2d7a5d3a96909a18d5fa80548534951efb24af6ec83e", size = 8820009, upload-time = "2026-03-08T16:57:36.865Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ef/818c68d9b407e3d02fbe7e39ad73750846d19afad50c4c9ad86455214fc2/zizmor-1.23.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:c62059c75100d0bc1a19cd95a6dce9b93ac5ab2e7d7bcdd974c51b2c5eb503e3", size = 8331336, upload-time = "2026-03-08T16:57:20.825Z" }, + { url = "https://files.pythonhosted.org/packages/28/bb/1c984e1474fcf5f08e5847838007668d2682e1fcbc109d481967736ab18f/zizmor-1.23.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:cf0dc93171e9ae7b822041471715ea7a9f5ebefa6865ceb6d1a39729a982d770", size = 9314682, upload-time = "2026-03-08T16:57:27.361Z" }, + { url = "https://files.pythonhosted.org/packages/fb/26/10f597f9b19ecd7bece2a1eb7d1ca1bd09d089d750d70365c76118056ec1/zizmor-1.23.1-py3-none-win32.whl", hash = "sha256:229c6b275941a18b03eef0ba5d24089dfbbe4fc34633a6b22bf924294ef69cde", size = 7464678, upload-time = "2026-03-08T16:57:30.569Z" }, + { url = "https://files.pythonhosted.org/packages/04/25/14071ea8ab5ebde85391d27e9de060d8a31a44eea448aba8d8bdd30693b3/zizmor-1.23.1-py3-none-win_amd64.whl", hash = "sha256:dc9befe3c08fea7d0fa3a0bc98073fadf31a77f0572b1f7931e1ff300337fe11", size = 8506938, upload-time = "2026-03-08T16:57:15.787Z" }, +] From 24db1286eb548f9130716cc8866df98d35ae2063 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 Apr 2026 12:21:29 +0000 Subject: [PATCH 65/69] =?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 95db49b28c..3537765f31 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* 🔒️ Add zizmor and fix audit findings. PR [#15316](https://github.com/fastapi/fastapi/pull/15316) by [@YuriiMotov](https://github.com/YuriiMotov). + ## 0.136.0 (2026-04-16) ### Upgrades From 3808d8540fe62cc55bafe723fb276094e6d7e27d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 16 Apr 2026 14:42:27 +0200 Subject: [PATCH 66/69] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20remov?= =?UTF-8?q?e=20Speakeasy=20(#15368)?= 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/docs/advanced/generate-clients.md | 1 - 3 files changed, 5 deletions(-) diff --git a/README.md b/README.md index 0b7fcc1c51..1875f2ba5b 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,6 @@ The key features are: - diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index f8085b4523..901160534a 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -40,9 +40,6 @@ silver: - 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 - title: SDKs for your API | Speakeasy - img: https://fastapi.tiangolo.com/img/sponsors/speakeasy.png - url: https://www.svix.com/ title: Svix - Webhooks as a service img: https://fastapi.tiangolo.com/img/sponsors/svix.svg diff --git a/docs/en/docs/advanced/generate-clients.md b/docs/en/docs/advanced/generate-clients.md index 9e0abaacc3..1fff3c9dc5 100644 --- a/docs/en/docs/advanced/generate-clients.md +++ b/docs/en/docs/advanced/generate-clients.md @@ -30,7 +30,6 @@ Their sponsorship also demonstrates a strong commitment to the FastAPI **communi For example, you might want to try: -* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) * [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) * [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) From 6976b0d4e62b5054526063d29259c1cddb2f11fe Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 Apr 2026 12:42:52 +0000 Subject: [PATCH 67/69] =?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 3537765f31..1bab73242d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* 🔧 Update sponsors: remove Speakeasy. PR [#15368](https://github.com/fastapi/fastapi/pull/15368) by [@tiangolo](https://github.com/tiangolo). * 🔒️ Add zizmor and fix audit findings. PR [#15316](https://github.com/fastapi/fastapi/pull/15316) by [@YuriiMotov](https://github.com/YuriiMotov). ## 0.136.0 (2026-04-16) From 41df44a29c986a908527fae7d3cdd613fb9fadb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 16 Apr 2026 14:47:22 +0200 Subject: [PATCH 68/69] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20remov?= =?UTF-8?q?e=20Zuplo=20(#15369)?= 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 1875f2ba5b..9ed338a1bb 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,6 @@ The key features are: - diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 901160534a..ea9eec0de0 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -12,9 +12,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://zuplo.link/fastapi-gh - 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 img: https://fastapi.tiangolo.com/img/sponsors/liblab.png diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index a37ebf0a4c..54c36fbc7b 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -51,12 +51,6 @@
-