committed by
GitHub
20 changed files with 1321 additions and 333 deletions
@ -1,495 +1,495 @@ |
|||||
- name: full-stack-fastapi-template |
- name: full-stack-fastapi-template |
||||
html_url: https://github.com/fastapi/full-stack-fastapi-template |
html_url: https://github.com/fastapi/full-stack-fastapi-template |
||||
stars: 33079 |
stars: 34156 |
||||
owner_login: fastapi |
owner_login: fastapi |
||||
owner_html_url: https://github.com/fastapi |
owner_html_url: https://github.com/fastapi |
||||
- name: Hello-Python |
- name: Hello-Python |
||||
html_url: https://github.com/mouredev/Hello-Python |
html_url: https://github.com/mouredev/Hello-Python |
||||
stars: 30350 |
stars: 30835 |
||||
owner_login: mouredev |
owner_login: mouredev |
||||
owner_html_url: https://github.com/mouredev |
owner_html_url: https://github.com/mouredev |
||||
- name: serve |
- name: serve |
||||
html_url: https://github.com/jina-ai/serve |
html_url: https://github.com/jina-ai/serve |
||||
stars: 21593 |
stars: 21631 |
||||
owner_login: jina-ai |
owner_login: jina-ai |
||||
owner_html_url: https://github.com/jina-ai |
owner_html_url: https://github.com/jina-ai |
||||
- name: HivisionIDPhotos |
- name: HivisionIDPhotos |
||||
html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos |
html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos |
||||
stars: 17229 |
stars: 18125 |
||||
owner_login: Zeyi-Lin |
owner_login: Zeyi-Lin |
||||
owner_html_url: https://github.com/Zeyi-Lin |
owner_html_url: https://github.com/Zeyi-Lin |
||||
- name: sqlmodel |
- name: sqlmodel |
||||
html_url: https://github.com/fastapi/sqlmodel |
html_url: https://github.com/fastapi/sqlmodel |
||||
stars: 16068 |
stars: 16249 |
||||
owner_login: fastapi |
owner_login: fastapi |
||||
owner_html_url: https://github.com/fastapi |
owner_html_url: https://github.com/fastapi |
||||
- name: Douyin_TikTok_Download_API |
- name: Douyin_TikTok_Download_API |
||||
html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API |
html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API |
||||
stars: 12689 |
stars: 13279 |
||||
owner_login: Evil0ctal |
owner_login: Evil0ctal |
||||
owner_html_url: https://github.com/Evil0ctal |
owner_html_url: https://github.com/Evil0ctal |
||||
- name: fastapi-best-practices |
- name: fastapi-best-practices |
||||
html_url: https://github.com/zhanymkanov/fastapi-best-practices |
html_url: https://github.com/zhanymkanov/fastapi-best-practices |
||||
stars: 11965 |
stars: 12334 |
||||
owner_login: zhanymkanov |
owner_login: zhanymkanov |
||||
owner_html_url: https://github.com/zhanymkanov |
owner_html_url: https://github.com/zhanymkanov |
||||
- name: awesome-fastapi |
- name: awesome-fastapi |
||||
html_url: https://github.com/mjhea0/awesome-fastapi |
html_url: https://github.com/mjhea0/awesome-fastapi |
||||
stars: 9773 |
stars: 9934 |
||||
owner_login: mjhea0 |
owner_login: mjhea0 |
||||
owner_html_url: https://github.com/mjhea0 |
owner_html_url: https://github.com/mjhea0 |
||||
- name: FastUI |
- name: FastUI |
||||
html_url: https://github.com/pydantic/FastUI |
html_url: https://github.com/pydantic/FastUI |
||||
stars: 8829 |
stars: 8838 |
||||
owner_login: pydantic |
owner_login: pydantic |
||||
owner_html_url: https://github.com/pydantic |
owner_html_url: https://github.com/pydantic |
||||
|
- name: XHS-Downloader |
||||
|
html_url: https://github.com/JoeanAmier/XHS-Downloader |
||||
|
stars: 7962 |
||||
|
owner_login: JoeanAmier |
||||
|
owner_html_url: https://github.com/JoeanAmier |
||||
- name: nonebot2 |
- name: nonebot2 |
||||
html_url: https://github.com/nonebot/nonebot2 |
html_url: https://github.com/nonebot/nonebot2 |
||||
stars: 6779 |
stars: 6834 |
||||
owner_login: nonebot |
owner_login: nonebot |
||||
owner_html_url: https://github.com/nonebot |
owner_html_url: https://github.com/nonebot |
||||
- name: FileCodeBox |
- name: FileCodeBox |
||||
html_url: https://github.com/vastsa/FileCodeBox |
html_url: https://github.com/vastsa/FileCodeBox |
||||
stars: 6652 |
stars: 6783 |
||||
owner_login: vastsa |
owner_login: vastsa |
||||
owner_html_url: https://github.com/vastsa |
owner_html_url: https://github.com/vastsa |
||||
- name: serge |
- name: fastapi_mcp |
||||
html_url: https://github.com/serge-chat/serge |
html_url: https://github.com/tadata-org/fastapi_mcp |
||||
stars: 5722 |
stars: 5846 |
||||
owner_login: serge-chat |
owner_login: tadata-org |
||||
owner_html_url: https://github.com/serge-chat |
owner_html_url: https://github.com/tadata-org |
||||
- name: hatchet |
- name: hatchet |
||||
html_url: https://github.com/hatchet-dev/hatchet |
html_url: https://github.com/hatchet-dev/hatchet |
||||
stars: 5607 |
stars: 5773 |
||||
owner_login: hatchet-dev |
owner_login: hatchet-dev |
||||
owner_html_url: https://github.com/hatchet-dev |
owner_html_url: https://github.com/hatchet-dev |
||||
|
- name: serge |
||||
|
html_url: https://github.com/serge-chat/serge |
||||
|
stars: 5728 |
||||
|
owner_login: serge-chat |
||||
|
owner_html_url: https://github.com/serge-chat |
||||
- name: polar |
- name: polar |
||||
html_url: https://github.com/polarsource/polar |
html_url: https://github.com/polarsource/polar |
||||
stars: 5327 |
stars: 5709 |
||||
owner_login: polarsource |
owner_login: polarsource |
||||
owner_html_url: https://github.com/polarsource |
owner_html_url: https://github.com/polarsource |
||||
- name: fastapi-users |
- name: fastapi-users |
||||
html_url: https://github.com/fastapi-users/fastapi-users |
html_url: https://github.com/fastapi-users/fastapi-users |
||||
stars: 5235 |
stars: 5336 |
||||
owner_login: fastapi-users |
owner_login: fastapi-users |
||||
owner_html_url: https://github.com/fastapi-users |
owner_html_url: https://github.com/fastapi-users |
||||
- name: fastapi_mcp |
|
||||
html_url: https://github.com/tadata-org/fastapi_mcp |
|
||||
stars: 5193 |
|
||||
owner_login: tadata-org |
|
||||
owner_html_url: https://github.com/tadata-org |
|
||||
- name: SurfSense |
|
||||
html_url: https://github.com/MODSetter/SurfSense |
|
||||
stars: 4833 |
|
||||
owner_login: MODSetter |
|
||||
owner_html_url: https://github.com/MODSetter |
|
||||
- name: chatgpt-web-share |
|
||||
html_url: https://github.com/chatpire/chatgpt-web-share |
|
||||
stars: 4307 |
|
||||
owner_login: chatpire |
|
||||
owner_html_url: https://github.com/chatpire |
|
||||
- name: strawberry |
- name: strawberry |
||||
html_url: https://github.com/strawberry-graphql/strawberry |
html_url: https://github.com/strawberry-graphql/strawberry |
||||
stars: 4281 |
stars: 4317 |
||||
owner_login: strawberry-graphql |
owner_login: strawberry-graphql |
||||
owner_html_url: https://github.com/strawberry-graphql |
owner_html_url: https://github.com/strawberry-graphql |
||||
|
- name: chatgpt-web-share |
||||
|
html_url: https://github.com/chatpire/chatgpt-web-share |
||||
|
stars: 4301 |
||||
|
owner_login: chatpire |
||||
|
owner_html_url: https://github.com/chatpire |
||||
- name: atrilabs-engine |
- name: atrilabs-engine |
||||
html_url: https://github.com/Atri-Labs/atrilabs-engine |
html_url: https://github.com/Atri-Labs/atrilabs-engine |
||||
stars: 4110 |
stars: 4106 |
||||
owner_login: Atri-Labs |
owner_login: Atri-Labs |
||||
owner_html_url: https://github.com/Atri-Labs |
owner_html_url: https://github.com/Atri-Labs |
||||
- name: dynaconf |
- name: dynaconf |
||||
html_url: https://github.com/dynaconf/dynaconf |
html_url: https://github.com/dynaconf/dynaconf |
||||
stars: 4008 |
stars: 4045 |
||||
owner_login: dynaconf |
owner_login: dynaconf |
||||
owner_html_url: https://github.com/dynaconf |
owner_html_url: https://github.com/dynaconf |
||||
- name: poem |
- name: poem |
||||
html_url: https://github.com/poem-web/poem |
html_url: https://github.com/poem-web/poem |
||||
stars: 3977 |
stars: 4037 |
||||
owner_login: poem-web |
owner_login: poem-web |
||||
owner_html_url: https://github.com/poem-web |
owner_html_url: https://github.com/poem-web |
||||
- name: farfalle |
- name: farfalle |
||||
html_url: https://github.com/rashadphz/farfalle |
html_url: https://github.com/rashadphz/farfalle |
||||
stars: 3317 |
stars: 3348 |
||||
owner_login: rashadphz |
owner_login: rashadphz |
||||
owner_html_url: https://github.com/rashadphz |
owner_html_url: https://github.com/rashadphz |
||||
|
- name: LitServe |
||||
|
html_url: https://github.com/Lightning-AI/LitServe |
||||
|
stars: 3347 |
||||
|
owner_login: Lightning-AI |
||||
|
owner_html_url: https://github.com/Lightning-AI |
||||
- name: fastapi-admin |
- name: fastapi-admin |
||||
html_url: https://github.com/fastapi-admin/fastapi-admin |
html_url: https://github.com/fastapi-admin/fastapi-admin |
||||
stars: 3253 |
stars: 3309 |
||||
owner_login: fastapi-admin |
owner_login: fastapi-admin |
||||
owner_html_url: https://github.com/fastapi-admin |
owner_html_url: https://github.com/fastapi-admin |
||||
- name: datamodel-code-generator |
- name: datamodel-code-generator |
||||
html_url: https://github.com/koxudaxi/datamodel-code-generator |
html_url: https://github.com/koxudaxi/datamodel-code-generator |
||||
stars: 3228 |
stars: 3291 |
||||
owner_login: koxudaxi |
owner_login: koxudaxi |
||||
owner_html_url: https://github.com/koxudaxi |
owner_html_url: https://github.com/koxudaxi |
||||
- name: LitServe |
|
||||
html_url: https://github.com/Lightning-AI/LitServe |
|
||||
stars: 3175 |
|
||||
owner_login: Lightning-AI |
|
||||
owner_html_url: https://github.com/Lightning-AI |
|
||||
- name: logfire |
- name: logfire |
||||
html_url: https://github.com/pydantic/logfire |
html_url: https://github.com/pydantic/logfire |
||||
stars: 3172 |
stars: 3288 |
||||
owner_login: pydantic |
owner_login: pydantic |
||||
owner_html_url: https://github.com/pydantic |
owner_html_url: https://github.com/pydantic |
||||
- name: opyrator |
|
||||
html_url: https://github.com/ml-tooling/opyrator |
|
||||
stars: 3122 |
|
||||
owner_login: ml-tooling |
|
||||
owner_html_url: https://github.com/ml-tooling |
|
||||
- name: huma |
- name: huma |
||||
html_url: https://github.com/danielgtaylor/huma |
html_url: https://github.com/danielgtaylor/huma |
||||
stars: 3110 |
stars: 3201 |
||||
owner_login: danielgtaylor |
owner_login: danielgtaylor |
||||
owner_html_url: https://github.com/danielgtaylor |
owner_html_url: https://github.com/danielgtaylor |
||||
|
- name: opyrator |
||||
|
html_url: https://github.com/ml-tooling/opyrator |
||||
|
stars: 3132 |
||||
|
owner_login: ml-tooling |
||||
|
owner_html_url: https://github.com/ml-tooling |
||||
|
- name: Kokoro-FastAPI |
||||
|
html_url: https://github.com/remsky/Kokoro-FastAPI |
||||
|
stars: 3099 |
||||
|
owner_login: remsky |
||||
|
owner_html_url: https://github.com/remsky |
||||
- name: docarray |
- name: docarray |
||||
html_url: https://github.com/docarray/docarray |
html_url: https://github.com/docarray/docarray |
||||
stars: 3068 |
stars: 3075 |
||||
owner_login: docarray |
owner_login: docarray |
||||
owner_html_url: https://github.com/docarray |
owner_html_url: https://github.com/docarray |
||||
- name: fastapi-realworld-example-app |
- name: fastapi-realworld-example-app |
||||
html_url: https://github.com/nsidnev/fastapi-realworld-example-app |
html_url: https://github.com/nsidnev/fastapi-realworld-example-app |
||||
stars: 2892 |
stars: 2902 |
||||
owner_login: nsidnev |
owner_login: nsidnev |
||||
owner_html_url: https://github.com/nsidnev |
owner_html_url: https://github.com/nsidnev |
||||
- name: Kokoro-FastAPI |
|
||||
html_url: https://github.com/remsky/Kokoro-FastAPI |
|
||||
stars: 2883 |
|
||||
owner_login: remsky |
|
||||
owner_html_url: https://github.com/remsky |
|
||||
- name: uvicorn-gunicorn-fastapi-docker |
|
||||
html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker |
|
||||
stars: 2770 |
|
||||
owner_login: tiangolo |
|
||||
owner_html_url: https://github.com/tiangolo |
|
||||
- name: tracecat |
- name: tracecat |
||||
html_url: https://github.com/TracecatHQ/tracecat |
html_url: https://github.com/TracecatHQ/tracecat |
||||
stars: 2740 |
stars: 2888 |
||||
owner_login: TracecatHQ |
owner_login: TracecatHQ |
||||
owner_html_url: https://github.com/TracecatHQ |
owner_html_url: https://github.com/TracecatHQ |
||||
|
- name: uvicorn-gunicorn-fastapi-docker |
||||
|
html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker |
||||
|
stars: 2775 |
||||
|
owner_login: tiangolo |
||||
|
owner_html_url: https://github.com/tiangolo |
||||
- name: best-of-web-python |
- name: best-of-web-python |
||||
html_url: https://github.com/ml-tooling/best-of-web-python |
html_url: https://github.com/ml-tooling/best-of-web-python |
||||
stars: 2517 |
stars: 2537 |
||||
owner_login: ml-tooling |
owner_login: ml-tooling |
||||
owner_html_url: https://github.com/ml-tooling |
owner_html_url: https://github.com/ml-tooling |
||||
- name: RasaGPT |
- name: RasaGPT |
||||
html_url: https://github.com/paulpierre/RasaGPT |
html_url: https://github.com/paulpierre/RasaGPT |
||||
stars: 2423 |
stars: 2427 |
||||
owner_login: paulpierre |
owner_login: paulpierre |
||||
owner_html_url: https://github.com/paulpierre |
owner_html_url: https://github.com/paulpierre |
||||
- name: fastapi-react |
- name: fastapi-react |
||||
html_url: https://github.com/Buuntu/fastapi-react |
html_url: https://github.com/Buuntu/fastapi-react |
||||
stars: 2376 |
stars: 2397 |
||||
owner_login: Buuntu |
owner_login: Buuntu |
||||
owner_html_url: https://github.com/Buuntu |
owner_html_url: https://github.com/Buuntu |
||||
- name: FastAPI-template |
- name: FastAPI-template |
||||
html_url: https://github.com/s3rius/FastAPI-template |
html_url: https://github.com/s3rius/FastAPI-template |
||||
stars: 2301 |
stars: 2334 |
||||
owner_login: s3rius |
owner_login: s3rius |
||||
owner_html_url: https://github.com/s3rius |
owner_html_url: https://github.com/s3rius |
||||
- name: nextpy |
- name: nextpy |
||||
html_url: https://github.com/dot-agent/nextpy |
html_url: https://github.com/dot-agent/nextpy |
||||
stars: 2289 |
stars: 2295 |
||||
owner_login: dot-agent |
owner_login: dot-agent |
||||
owner_html_url: https://github.com/dot-agent |
owner_html_url: https://github.com/dot-agent |
||||
- name: sqladmin |
- name: sqladmin |
||||
html_url: https://github.com/aminalaee/sqladmin |
html_url: https://github.com/aminalaee/sqladmin |
||||
stars: 2196 |
stars: 2235 |
||||
owner_login: aminalaee |
owner_login: aminalaee |
||||
owner_html_url: https://github.com/aminalaee |
owner_html_url: https://github.com/aminalaee |
||||
- name: 30-Days-of-Python |
- name: 30-Days-of-Python |
||||
html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python |
html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python |
||||
stars: 2179 |
stars: 2181 |
||||
owner_login: codingforentrepreneurs |
owner_login: codingforentrepreneurs |
||||
owner_html_url: https://github.com/codingforentrepreneurs |
owner_html_url: https://github.com/codingforentrepreneurs |
||||
- name: langserve |
- name: langserve |
||||
html_url: https://github.com/langchain-ai/langserve |
html_url: https://github.com/langchain-ai/langserve |
||||
stars: 2098 |
stars: 2119 |
||||
owner_login: langchain-ai |
owner_login: langchain-ai |
||||
owner_html_url: https://github.com/langchain-ai |
owner_html_url: https://github.com/langchain-ai |
||||
- name: fastapi-utils |
- name: fastapi-utils |
||||
html_url: https://github.com/fastapiutils/fastapi-utils |
html_url: https://github.com/fastapiutils/fastapi-utils |
||||
stars: 2077 |
stars: 2100 |
||||
owner_login: fastapiutils |
owner_login: fastapiutils |
||||
owner_html_url: https://github.com/fastapiutils |
owner_html_url: https://github.com/fastapiutils |
||||
- name: supabase-py |
- name: supabase-py |
||||
html_url: https://github.com/supabase/supabase-py |
html_url: https://github.com/supabase/supabase-py |
||||
stars: 2047 |
stars: 2084 |
||||
owner_login: supabase |
owner_login: supabase |
||||
owner_html_url: https://github.com/supabase |
owner_html_url: https://github.com/supabase |
||||
- name: solara |
- name: solara |
||||
html_url: https://github.com/widgetti/solara |
html_url: https://github.com/widgetti/solara |
||||
stars: 2044 |
stars: 2056 |
||||
owner_login: widgetti |
owner_login: widgetti |
||||
owner_html_url: https://github.com/widgetti |
owner_html_url: https://github.com/widgetti |
||||
- name: mangum |
- name: mangum |
||||
html_url: https://github.com/Kludex/mangum |
html_url: https://github.com/Kludex/mangum |
||||
stars: 1905 |
stars: 1923 |
||||
owner_login: Kludex |
owner_login: Kludex |
||||
owner_html_url: https://github.com/Kludex |
owner_html_url: https://github.com/Kludex |
||||
- name: python-week-2022 |
- name: python-week-2022 |
||||
html_url: https://github.com/rochacbruno/python-week-2022 |
html_url: https://github.com/rochacbruno/python-week-2022 |
||||
stars: 1823 |
stars: 1821 |
||||
owner_login: rochacbruno |
owner_login: rochacbruno |
||||
owner_html_url: https://github.com/rochacbruno |
owner_html_url: https://github.com/rochacbruno |
||||
- name: manage-fastapi |
|
||||
html_url: https://github.com/ycd/manage-fastapi |
|
||||
stars: 1754 |
|
||||
owner_login: ycd |
|
||||
owner_html_url: https://github.com/ycd |
|
||||
- name: agentkit |
- name: agentkit |
||||
html_url: https://github.com/BCG-X-Official/agentkit |
html_url: https://github.com/BCG-X-Official/agentkit |
||||
stars: 1746 |
stars: 1765 |
||||
owner_login: BCG-X-Official |
owner_login: BCG-X-Official |
||||
owner_html_url: https://github.com/BCG-X-Official |
owner_html_url: https://github.com/BCG-X-Official |
||||
|
- name: manage-fastapi |
||||
|
html_url: https://github.com/ycd/manage-fastapi |
||||
|
stars: 1756 |
||||
|
owner_login: ycd |
||||
|
owner_html_url: https://github.com/ycd |
||||
- name: ormar |
- name: ormar |
||||
html_url: https://github.com/collerek/ormar |
html_url: https://github.com/collerek/ormar |
||||
stars: 1742 |
stars: 1755 |
||||
owner_login: collerek |
owner_login: collerek |
||||
owner_html_url: https://github.com/collerek |
owner_html_url: https://github.com/collerek |
||||
- name: langchain-serve |
- name: langchain-serve |
||||
html_url: https://github.com/jina-ai/langchain-serve |
html_url: https://github.com/jina-ai/langchain-serve |
||||
stars: 1630 |
stars: 1631 |
||||
owner_login: jina-ai |
owner_login: jina-ai |
||||
owner_html_url: https://github.com/jina-ai |
owner_html_url: https://github.com/jina-ai |
||||
- name: termpair |
|
||||
html_url: https://github.com/cs01/termpair |
|
||||
stars: 1611 |
|
||||
owner_login: cs01 |
|
||||
owner_html_url: https://github.com/cs01 |
|
||||
- name: piccolo |
- name: piccolo |
||||
html_url: https://github.com/piccolo-orm/piccolo |
html_url: https://github.com/piccolo-orm/piccolo |
||||
stars: 1609 |
stars: 1629 |
||||
owner_login: piccolo-orm |
owner_login: piccolo-orm |
||||
owner_html_url: https://github.com/piccolo-orm |
owner_html_url: https://github.com/piccolo-orm |
||||
- name: coronavirus-tracker-api |
- name: termpair |
||||
html_url: https://github.com/ExpDev07/coronavirus-tracker-api |
html_url: https://github.com/cs01/termpair |
||||
stars: 1587 |
stars: 1616 |
||||
owner_login: ExpDev07 |
owner_login: cs01 |
||||
owner_html_url: https://github.com/ExpDev07 |
owner_html_url: https://github.com/cs01 |
||||
- name: fastapi-cache |
|
||||
html_url: https://github.com/long2ice/fastapi-cache |
|
||||
stars: 1575 |
|
||||
owner_login: long2ice |
|
||||
owner_html_url: https://github.com/long2ice |
|
||||
- name: openapi-python-client |
- name: openapi-python-client |
||||
html_url: https://github.com/openapi-generators/openapi-python-client |
html_url: https://github.com/openapi-generators/openapi-python-client |
||||
stars: 1568 |
stars: 1603 |
||||
owner_login: openapi-generators |
owner_login: openapi-generators |
||||
owner_html_url: https://github.com/openapi-generators |
owner_html_url: https://github.com/openapi-generators |
||||
- name: fastapi-crudrouter |
- name: fastapi-cache |
||||
html_url: https://github.com/awtkns/fastapi-crudrouter |
html_url: https://github.com/long2ice/fastapi-cache |
||||
stars: 1508 |
stars: 1589 |
||||
owner_login: awtkns |
owner_login: long2ice |
||||
owner_html_url: https://github.com/awtkns |
owner_html_url: https://github.com/long2ice |
||||
|
- name: coronavirus-tracker-api |
||||
|
html_url: https://github.com/ExpDev07/coronavirus-tracker-api |
||||
|
stars: 1580 |
||||
|
owner_login: ExpDev07 |
||||
|
owner_html_url: https://github.com/ExpDev07 |
||||
- name: slowapi |
- name: slowapi |
||||
html_url: https://github.com/laurentS/slowapi |
html_url: https://github.com/laurentS/slowapi |
||||
stars: 1501 |
stars: 1533 |
||||
owner_login: laurentS |
owner_login: laurentS |
||||
owner_html_url: https://github.com/laurentS |
owner_html_url: https://github.com/laurentS |
||||
|
- name: fastapi-crudrouter |
||||
|
html_url: https://github.com/awtkns/fastapi-crudrouter |
||||
|
stars: 1518 |
||||
|
owner_login: awtkns |
||||
|
owner_html_url: https://github.com/awtkns |
||||
- name: awesome-fastapi-projects |
- name: awesome-fastapi-projects |
||||
html_url: https://github.com/Kludex/awesome-fastapi-projects |
html_url: https://github.com/Kludex/awesome-fastapi-projects |
||||
stars: 1453 |
stars: 1461 |
||||
owner_login: Kludex |
owner_login: Kludex |
||||
owner_html_url: https://github.com/Kludex |
owner_html_url: https://github.com/Kludex |
||||
|
- name: vue-fastapi-admin |
||||
|
html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin |
||||
|
stars: 1409 |
||||
|
owner_login: mizhexiaoxiao |
||||
|
owner_html_url: https://github.com/mizhexiaoxiao |
||||
- name: awesome-python-resources |
- name: awesome-python-resources |
||||
html_url: https://github.com/DjangoEx/awesome-python-resources |
html_url: https://github.com/DjangoEx/awesome-python-resources |
||||
stars: 1390 |
stars: 1393 |
||||
owner_login: DjangoEx |
owner_login: DjangoEx |
||||
owner_html_url: https://github.com/DjangoEx |
owner_html_url: https://github.com/DjangoEx |
||||
- name: fastapi-pagination |
- name: fastapi-pagination |
||||
html_url: https://github.com/uriyyo/fastapi-pagination |
html_url: https://github.com/uriyyo/fastapi-pagination |
||||
stars: 1353 |
stars: 1378 |
||||
owner_login: uriyyo |
owner_login: uriyyo |
||||
owner_html_url: https://github.com/uriyyo |
owner_html_url: https://github.com/uriyyo |
||||
- name: budgetml |
|
||||
html_url: https://github.com/ebhy/budgetml |
|
||||
stars: 1342 |
|
||||
owner_login: ebhy |
|
||||
owner_html_url: https://github.com/ebhy |
|
||||
- name: fastapi-boilerplate |
- name: fastapi-boilerplate |
||||
html_url: https://github.com/teamhide/fastapi-boilerplate |
html_url: https://github.com/teamhide/fastapi-boilerplate |
||||
stars: 1325 |
stars: 1348 |
||||
owner_login: teamhide |
owner_login: teamhide |
||||
owner_html_url: https://github.com/teamhide |
owner_html_url: https://github.com/teamhide |
||||
- name: vue-fastapi-admin |
- name: budgetml |
||||
html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin |
html_url: https://github.com/ebhy/budgetml |
||||
stars: 1306 |
stars: 1344 |
||||
owner_login: mizhexiaoxiao |
owner_login: ebhy |
||||
owner_html_url: https://github.com/mizhexiaoxiao |
owner_html_url: https://github.com/ebhy |
||||
- name: fastapi-amis-admin |
- name: fastapi-amis-admin |
||||
html_url: https://github.com/amisadmin/fastapi-amis-admin |
html_url: https://github.com/amisadmin/fastapi-amis-admin |
||||
stars: 1256 |
stars: 1284 |
||||
owner_login: amisadmin |
owner_login: amisadmin |
||||
owner_html_url: https://github.com/amisadmin |
owner_html_url: https://github.com/amisadmin |
||||
|
- name: bracket |
||||
|
html_url: https://github.com/evroon/bracket |
||||
|
stars: 1274 |
||||
|
owner_login: evroon |
||||
|
owner_html_url: https://github.com/evroon |
||||
- name: fastapi-tutorial |
- name: fastapi-tutorial |
||||
html_url: https://github.com/liaogx/fastapi-tutorial |
html_url: https://github.com/liaogx/fastapi-tutorial |
||||
stars: 1245 |
stars: 1265 |
||||
owner_login: liaogx |
owner_login: liaogx |
||||
owner_html_url: https://github.com/liaogx |
owner_html_url: https://github.com/liaogx |
||||
- name: fastapi-code-generator |
- name: fastapi-code-generator |
||||
html_url: https://github.com/koxudaxi/fastapi-code-generator |
html_url: https://github.com/koxudaxi/fastapi-code-generator |
||||
stars: 1201 |
stars: 1216 |
||||
owner_login: koxudaxi |
owner_login: koxudaxi |
||||
owner_html_url: https://github.com/koxudaxi |
owner_html_url: https://github.com/koxudaxi |
||||
- name: bracket |
|
||||
html_url: https://github.com/evroon/bracket |
|
||||
stars: 1201 |
|
||||
owner_login: evroon |
|
||||
owner_html_url: https://github.com/evroon |
|
||||
- name: bolt-python |
- name: bolt-python |
||||
html_url: https://github.com/slackapi/bolt-python |
html_url: https://github.com/slackapi/bolt-python |
||||
stars: 1179 |
stars: 1190 |
||||
owner_login: slackapi |
owner_login: slackapi |
||||
owner_html_url: https://github.com/slackapi |
owner_html_url: https://github.com/slackapi |
||||
- name: fastapi_production_template |
- name: fastcrud |
||||
html_url: https://github.com/zhanymkanov/fastapi_production_template |
html_url: https://github.com/benavlabs/fastcrud |
||||
stars: 1147 |
stars: 1169 |
||||
owner_login: zhanymkanov |
owner_login: benavlabs |
||||
owner_html_url: https://github.com/zhanymkanov |
owner_html_url: https://github.com/benavlabs |
||||
- name: prometheus-fastapi-instrumentator |
- name: prometheus-fastapi-instrumentator |
||||
html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator |
html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator |
||||
stars: 1145 |
stars: 1167 |
||||
owner_login: trallnag |
owner_login: trallnag |
||||
owner_html_url: https://github.com/trallnag |
owner_html_url: https://github.com/trallnag |
||||
|
- name: fastapi_production_template |
||||
|
html_url: https://github.com/zhanymkanov/fastapi_production_template |
||||
|
stars: 1165 |
||||
|
owner_login: zhanymkanov |
||||
|
owner_html_url: https://github.com/zhanymkanov |
||||
- name: bedrock-chat |
- name: bedrock-chat |
||||
html_url: https://github.com/aws-samples/bedrock-chat |
html_url: https://github.com/aws-samples/bedrock-chat |
||||
stars: 1143 |
stars: 1163 |
||||
owner_login: aws-samples |
owner_login: aws-samples |
||||
owner_html_url: https://github.com/aws-samples |
owner_html_url: https://github.com/aws-samples |
||||
- name: langchain-extract |
- name: langchain-extract |
||||
html_url: https://github.com/langchain-ai/langchain-extract |
html_url: https://github.com/langchain-ai/langchain-extract |
||||
stars: 1134 |
stars: 1142 |
||||
owner_login: langchain-ai |
owner_login: langchain-ai |
||||
owner_html_url: https://github.com/langchain-ai |
owner_html_url: https://github.com/langchain-ai |
||||
- name: odmantic |
- name: odmantic |
||||
html_url: https://github.com/art049/odmantic |
html_url: https://github.com/art049/odmantic |
||||
stars: 1118 |
stars: 1121 |
||||
owner_login: art049 |
owner_login: art049 |
||||
owner_html_url: https://github.com/art049 |
owner_html_url: https://github.com/art049 |
||||
|
- name: fastapi_best_architecture |
||||
|
html_url: https://github.com/fastapi-practices/fastapi_best_architecture |
||||
|
stars: 1118 |
||||
|
owner_login: fastapi-practices |
||||
|
owner_html_url: https://github.com/fastapi-practices |
||||
- name: fastapi-alembic-sqlmodel-async |
- name: fastapi-alembic-sqlmodel-async |
||||
html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async |
html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async |
||||
stars: 1110 |
stars: 1116 |
||||
owner_login: jonra1993 |
owner_login: jonra1993 |
||||
owner_html_url: https://github.com/jonra1993 |
owner_html_url: https://github.com/jonra1993 |
||||
- name: fastcrud |
- name: FastAPI-boilerplate |
||||
html_url: https://github.com/benavlabs/fastcrud |
html_url: https://github.com/benavlabs/FastAPI-boilerplate |
||||
stars: 1080 |
stars: 1070 |
||||
owner_login: benavlabs |
owner_login: benavlabs |
||||
owner_html_url: https://github.com/benavlabs |
owner_html_url: https://github.com/benavlabs |
||||
- name: restish |
- name: restish |
||||
html_url: https://github.com/rest-sh/restish |
html_url: https://github.com/rest-sh/restish |
||||
stars: 1056 |
stars: 1069 |
||||
owner_login: rest-sh |
owner_login: rest-sh |
||||
owner_html_url: https://github.com/rest-sh |
owner_html_url: https://github.com/rest-sh |
||||
- name: fastapi_best_architecture |
|
||||
html_url: https://github.com/fastapi-practices/fastapi_best_architecture |
|
||||
stars: 1050 |
|
||||
owner_login: fastapi-practices |
|
||||
owner_html_url: https://github.com/fastapi-practices |
|
||||
- name: runhouse |
- name: runhouse |
||||
html_url: https://github.com/run-house/runhouse |
html_url: https://github.com/run-house/runhouse |
||||
stars: 1034 |
stars: 1037 |
||||
owner_login: run-house |
owner_login: run-house |
||||
owner_html_url: https://github.com/run-house |
owner_html_url: https://github.com/run-house |
||||
- name: autollm |
- name: autollm |
||||
html_url: https://github.com/viddexa/autollm |
html_url: https://github.com/viddexa/autollm |
||||
stars: 992 |
stars: 994 |
||||
owner_login: viddexa |
owner_login: viddexa |
||||
owner_html_url: https://github.com/viddexa |
owner_html_url: https://github.com/viddexa |
||||
- name: lanarky |
- name: lanarky |
||||
html_url: https://github.com/ajndkr/lanarky |
html_url: https://github.com/ajndkr/lanarky |
||||
stars: 990 |
stars: 992 |
||||
owner_login: ajndkr |
owner_login: ajndkr |
||||
owner_html_url: https://github.com/ajndkr |
owner_html_url: https://github.com/ajndkr |
||||
- name: FastAPI-boilerplate |
|
||||
html_url: https://github.com/benavlabs/FastAPI-boilerplate |
|
||||
stars: 985 |
|
||||
owner_login: benavlabs |
|
||||
owner_html_url: https://github.com/benavlabs |
|
||||
- name: authx |
- name: authx |
||||
html_url: https://github.com/yezz123/authx |
html_url: https://github.com/yezz123/authx |
||||
stars: 938 |
stars: 953 |
||||
owner_login: yezz123 |
owner_login: yezz123 |
||||
owner_html_url: https://github.com/yezz123 |
owner_html_url: https://github.com/yezz123 |
||||
- name: secure |
- name: secure |
||||
html_url: https://github.com/TypeError/secure |
html_url: https://github.com/TypeError/secure |
||||
stars: 935 |
stars: 941 |
||||
owner_login: TypeError |
owner_login: TypeError |
||||
owner_html_url: https://github.com/TypeError |
owner_html_url: https://github.com/TypeError |
||||
- name: langcorn |
|
||||
html_url: https://github.com/msoedov/langcorn |
|
||||
stars: 925 |
|
||||
owner_login: msoedov |
|
||||
owner_html_url: https://github.com/msoedov |
|
||||
- name: energy-forecasting |
- name: energy-forecasting |
||||
html_url: https://github.com/iusztinpaul/energy-forecasting |
html_url: https://github.com/iusztinpaul/energy-forecasting |
||||
stars: 913 |
stars: 928 |
||||
owner_login: iusztinpaul |
owner_login: iusztinpaul |
||||
owner_html_url: https://github.com/iusztinpaul |
owner_html_url: https://github.com/iusztinpaul |
||||
|
- name: langcorn |
||||
|
html_url: https://github.com/msoedov/langcorn |
||||
|
stars: 927 |
||||
|
owner_login: msoedov |
||||
|
owner_html_url: https://github.com/msoedov |
||||
- name: titiler |
- name: titiler |
||||
html_url: https://github.com/developmentseed/titiler |
html_url: https://github.com/developmentseed/titiler |
||||
stars: 886 |
stars: 901 |
||||
owner_login: developmentseed |
owner_login: developmentseed |
||||
owner_html_url: https://github.com/developmentseed |
owner_html_url: https://github.com/developmentseed |
||||
- name: flock |
- name: flock |
||||
html_url: https://github.com/Onelevenvy/flock |
html_url: https://github.com/Onelevenvy/flock |
||||
stars: 866 |
stars: 896 |
||||
owner_login: Onelevenvy |
owner_login: Onelevenvy |
||||
owner_html_url: https://github.com/Onelevenvy |
owner_html_url: https://github.com/Onelevenvy |
||||
- name: httpdbg |
- name: fastapi-langgraph-agent-production-ready-template |
||||
html_url: https://github.com/cle-b/httpdbg |
html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template |
||||
stars: 863 |
stars: 896 |
||||
owner_login: cle-b |
owner_login: wassim249 |
||||
owner_html_url: https://github.com/cle-b |
owner_html_url: https://github.com/wassim249 |
||||
- name: marker-api |
- name: marker-api |
||||
html_url: https://github.com/adithya-s-k/marker-api |
html_url: https://github.com/adithya-s-k/marker-api |
||||
stars: 859 |
stars: 875 |
||||
owner_login: adithya-s-k |
owner_login: adithya-s-k |
||||
owner_html_url: https://github.com/adithya-s-k |
owner_html_url: https://github.com/adithya-s-k |
||||
- name: ludic |
- name: httpdbg |
||||
html_url: https://github.com/getludic/ludic |
html_url: https://github.com/cle-b/httpdbg |
||||
stars: 845 |
stars: 870 |
||||
owner_login: getludic |
owner_login: cle-b |
||||
owner_html_url: https://github.com/getludic |
owner_html_url: https://github.com/cle-b |
||||
- name: fastapi-do-zero |
- name: fastapi-do-zero |
||||
html_url: https://github.com/dunossauro/fastapi-do-zero |
html_url: https://github.com/dunossauro/fastapi-do-zero |
||||
stars: 827 |
stars: 855 |
||||
owner_login: dunossauro |
owner_login: dunossauro |
||||
owner_html_url: https://github.com/dunossauro |
owner_html_url: https://github.com/dunossauro |
||||
|
- name: ludic |
||||
|
html_url: https://github.com/getludic/ludic |
||||
|
stars: 849 |
||||
|
owner_login: getludic |
||||
|
owner_html_url: https://github.com/getludic |
||||
- name: fastapi-observability |
- name: fastapi-observability |
||||
html_url: https://github.com/blueswen/fastapi-observability |
html_url: https://github.com/blueswen/fastapi-observability |
||||
stars: 823 |
stars: 837 |
||||
owner_login: blueswen |
owner_login: blueswen |
||||
owner_html_url: https://github.com/blueswen |
owner_html_url: https://github.com/blueswen |
||||
- name: fastapi-langgraph-agent-production-ready-template |
- name: fastapi-scaf |
||||
html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template |
html_url: https://github.com/atpuxiner/fastapi-scaf |
||||
stars: 803 |
stars: 821 |
||||
owner_login: wassim249 |
owner_login: atpuxiner |
||||
owner_html_url: https://github.com/wassim249 |
owner_html_url: https://github.com/atpuxiner |
||||
- name: fastapi-mail |
|
||||
html_url: https://github.com/sabuhish/fastapi-mail |
|
||||
stars: 798 |
|
||||
owner_login: sabuhish |
|
||||
owner_html_url: https://github.com/sabuhish |
|
||||
- name: starlette-admin |
- name: starlette-admin |
||||
html_url: https://github.com/jowilf/starlette-admin |
html_url: https://github.com/jowilf/starlette-admin |
||||
stars: 785 |
stars: 808 |
||||
owner_login: jowilf |
owner_login: jowilf |
||||
owner_html_url: https://github.com/jowilf |
owner_html_url: https://github.com/jowilf |
||||
- name: lccn_predictor |
- name: fastapi-mail |
||||
html_url: https://github.com/baoliay2008/lccn_predictor |
html_url: https://github.com/sabuhish/fastapi-mail |
||||
stars: 767 |
stars: 807 |
||||
owner_login: baoliay2008 |
owner_login: sabuhish |
||||
owner_html_url: https://github.com/baoliay2008 |
owner_html_url: https://github.com/sabuhish |
||||
- name: aktools |
- name: aktools |
||||
html_url: https://github.com/akfamily/aktools |
html_url: https://github.com/akfamily/aktools |
||||
stars: 759 |
stars: 796 |
||||
owner_login: akfamily |
owner_login: akfamily |
||||
owner_html_url: https://github.com/akfamily |
owner_html_url: https://github.com/akfamily |
||||
- name: KonomiTV |
- name: RuoYi-Vue3-FastAPI |
||||
html_url: https://github.com/tsukumijima/KonomiTV |
html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI |
||||
stars: 748 |
stars: 782 |
||||
owner_login: tsukumijima |
owner_login: insistence |
||||
owner_html_url: https://github.com/tsukumijima |
owner_html_url: https://github.com/insistence |
||||
|
@ -0,0 +1,41 @@ |
|||||
|
# Дополнительные статус коды |
||||
|
|
||||
|
По умолчанию **FastAPI** возвращает ответы, используя `JSONResponse`, помещая содержимое, которое вы возвращаете из вашей *операции пути*, внутрь этого `JSONResponse`. |
||||
|
|
||||
|
Он будет использовать код статуса по умолчанию или тот, который вы укажете в вашей *операции пути*. |
||||
|
|
||||
|
## Дополнительные статус коды |
||||
|
|
||||
|
Если вы хотите возвращать дополнительный статус код помимо основного, вы можете сделать это, возвращая объект `Response` напрямую, как `JSONResponse`, и устанавливая нужный статус код напрямую. |
||||
|
|
||||
|
Например, скажем, вы хотите создать *операцию пути*, которая позволяет обновлять элементы и возвращает HTTP-код 200 "OK" при успешном выполнении. |
||||
|
|
||||
|
Но вы также хотите, чтобы она принимала новые элементы. И если элемент ранее не существовал, он создаётся, и возвращался HTTP-код 201 "Created". |
||||
|
|
||||
|
Чтобы реализовать это, импортируйте `JSONResponse` и возвращайте ваш контент напрямую, устанавливая нужный `status_code`: |
||||
|
|
||||
|
{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} |
||||
|
|
||||
|
/// warning | Внимание |
||||
|
|
||||
|
Когда вы возвращаете объект `Response` напрямую, как в примере выше, он будет возвращён как есть. |
||||
|
|
||||
|
Он не будет сериализован при помощи модели и т.д. |
||||
|
|
||||
|
Убедитесь, что в нём содержатся именно те данные, которые вы хотите, и что значения являются валидным JSON (если вы используете `JSONResponse`). |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
/// note | Технические детали |
||||
|
|
||||
|
Вы также можете использовать `from starlette.responses import JSONResponse`. |
||||
|
|
||||
|
**FastAPI** предоставляет тот же `starlette.responses` через `fastapi.responses` просто для вашего удобства, как разработчика. Но большинство доступных Response-классов поступают напрямую из Starlette. То же самое касается и `status`. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## OpenAPI и документация API |
||||
|
|
||||
|
Если вы возвращаете дополнительные коды статусов и ответы напрямую, они не будут включены в схему OpenAPI (документацию API), потому что FastAPI не может заранее знать, что вы собираетесь вернуть. |
||||
|
|
||||
|
Но вы можете задокументировать это в вашем коде, используя: [Дополнительные ответы в OpenAPI](additional-responses.md){.internal-link target=_blank}. |
@ -0,0 +1,65 @@ |
|||||
|
# Возврат ответа напрямую |
||||
|
|
||||
|
Когда вы создаёте **FastAPI** *операцию пути*, вы можете возвращать из неё любые данные: `dict`, `list`, Pydantic-модель, модель базы данных и т.д. |
||||
|
|
||||
|
По умолчанию **FastAPI** автоматически преобразует возвращаемое значение в JSON с помощью `jsonable_encoder`, как описано в [JSON кодировщик](../tutorial/encoder.md){.internal-link target=_blank}. |
||||
|
|
||||
|
Затем "под капотом" эти данные, совместимые с JSON (например `dict`), помещаются в `JSONResponse`, который используется для отправки ответа клиенту. |
||||
|
|
||||
|
Но вы можете возвращать `JSONResponse` напрямую из ваших *операций пути*. |
||||
|
|
||||
|
Это может быть полезно, например, если нужно вернуть пользовательские заголовки или куки. |
||||
|
|
||||
|
## Возврат `Response` |
||||
|
|
||||
|
На самом деле, вы можете возвращать любой объект `Response` или его подкласс. |
||||
|
|
||||
|
/// tip | Подсказка |
||||
|
|
||||
|
`JSONResponse` сам по себе является подклассом `Response`. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
И когда вы возвращаете `Response`, **FastAPI** передаст его напрямую. |
||||
|
|
||||
|
Это не приведет к преобразованию данных с помощью Pydantic-моделей, содержимое не будет преобразовано в какой-либо тип и т.д. |
||||
|
|
||||
|
Это даёт вам большую гибкость. Вы можете возвращать любые типы данных, переопределять любые объявления или валидацию данных и т.д. |
||||
|
|
||||
|
## Использование `jsonable_encoder` в `Response` |
||||
|
|
||||
|
Поскольку **FastAPI** не изменяет объект `Response`, который вы возвращаете, вы должны убедиться, что его содержимое готово к отправке. |
||||
|
|
||||
|
Например, вы не можете поместить Pydantic-модель в `JSONResponse`, не преобразовав её сначала в `dict` с помощью преобразования всех типов данных (таких как `datetime`, `UUID` и т.д.) в совместимые с JSON типы. |
||||
|
|
||||
|
В таких случаях вы можете использовать `jsonable_encoder` для преобразования данных перед передачей их в ответ: |
||||
|
|
||||
|
{* ../../docs_src/response_directly/tutorial001.py hl[6:7,21:22] *} |
||||
|
|
||||
|
/// note | Технические детали |
||||
|
|
||||
|
Вы также можете использовать `from starlette.responses import JSONResponse`. |
||||
|
|
||||
|
**FastAPI** предоставляет `starlette.responses` через `fastapi.responses` просто для вашего удобства, как разработчика. Но большинство доступных Response-классов поступают напрямую из Starlette. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Возврат пользовательского `Response` |
||||
|
|
||||
|
Пример выше показывает все необходимые части, но он пока не очень полезен, так как вы могли бы просто вернуть `item` напрямую, и **FastAPI** поместил бы его в `JSONResponse`, преобразовав в `dict` и т.д. Всё это происходит по умолчанию. |
||||
|
|
||||
|
Теперь давайте посмотрим, как можно использовать это для возврата пользовательского ответа. |
||||
|
|
||||
|
Допустим, вы хотите вернуть ответ в формате <a href="https://en.wikipedia.org/wiki/XML" class="external-link" target="_blank">XML</a>. |
||||
|
|
||||
|
Вы можете поместить ваш XML-контент в строку, поместить её в `Response` и вернуть: |
||||
|
|
||||
|
{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} |
||||
|
|
||||
|
## Примечания |
||||
|
|
||||
|
Когда вы возвращаете объект `Response` напрямую, его данные не валидируются, не преобразуются (не сериализуются) и не документируются автоматически. |
||||
|
|
||||
|
Но вы всё равно можете задокументировать это, как описано в [Дополнительные ответы в OpenAPI](additional-responses.md){.internal-link target=_blank}. |
||||
|
|
||||
|
В следующих разделах вы увидите, как использовать/объявлять такие кастомные `Response`, при этом сохраняя автоматическое преобразование данных, документацию и т.д. |
@ -0,0 +1,116 @@ |
|||||
|
# Тіло – Оновлення |
||||
|
|
||||
|
## Оновлення з використанням `PUT` |
||||
|
|
||||
|
Щоб оновити елемент, Ви можете використати <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTP `PUT`</a> операцію. |
||||
|
|
||||
|
Ви можете використати `jsonable_encoder`, щоб перетворити вхідні дані на такі, які можна зберігати як JSON (наприклад, у NoSQL базі даних). Наприклад, перетворюючи `datetime` у `str`. |
||||
|
|
||||
|
{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *} |
||||
|
|
||||
|
`PUT` використовується для отримання даних, які мають замінити чинні дані. |
||||
|
|
||||
|
### Попередження про заміну |
||||
|
|
||||
|
Це означає, що якщо Ви хочете оновити елемент `bar`, використовуючи `PUT` з тілом: |
||||
|
|
||||
|
```Python |
||||
|
{ |
||||
|
"name": "Barz", |
||||
|
"price": 3, |
||||
|
"description": None, |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
оскільки він не містить вже збереженого атрибута `"tax": 20.2`, модель введення прийме значення за замовчуванням `"tax": 10.5`. |
||||
|
|
||||
|
І дані будуть збережені з цим "новим" значенням `tax` = `10.5`. |
||||
|
|
||||
|
## Часткові оновлення з `PATCH` |
||||
|
|
||||
|
Ви також можете використовувати операцію <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH" class="external-link" target="_blank">HTTP `PATCH`</a> для *часткового* оновлення даних. |
||||
|
|
||||
|
Це означає, що Ви можете надіслати лише ті дані, які хочете оновити, залишаючи інші без змін. |
||||
|
|
||||
|
/// note | Примітка |
||||
|
|
||||
|
`PATCH` менш відомий і рідше використовується, ніж `PUT`. |
||||
|
|
||||
|
І багато команд використовують лише `PUT`, навіть для часткових оновлень. |
||||
|
|
||||
|
Ви **вільні** використовувати їх так, як хочете, **FastAPI** не накладає обмежень. |
||||
|
|
||||
|
Але цей посібник показує Вам більш-менш як їх задумано використовувати. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
### Використання параметра `exclude_unset` у Pydantic |
||||
|
|
||||
|
Якщо Ви хочете отримати часткові оновлення, дуже зручно використовувати параметр `exclude_unset` у методі `.model_dump()` моделі Pydantic. |
||||
|
|
||||
|
Наприклад: `item.model_dump(exclude_unset=True)`. |
||||
|
|
||||
|
/// info | Інформація |
||||
|
|
||||
|
У Pydantic v1 цей метод називався `.dict()`, він був застарілий (але все ще підтримується) у Pydantic v2, і був перейменований у `.model_dump()`. |
||||
|
|
||||
|
Приклади тут використовують `.dict()` для сумісності з Pydantic v1, але Вам слід використовувати `.model_dump()`, якщо можете використовувати Pydantic v2. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
Це створить `dict` лише з тими даними, які були явно встановлені під час створення моделі `item`, виключаючи значення за замовчуванням. |
||||
|
|
||||
|
Тоді Ви можете використовувати це, щоб створити `dict` лише з даними, які були встановлені (надіслані у запиті), пропускаючи значення за замовчуванням: |
||||
|
|
||||
|
{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *} |
||||
|
|
||||
|
### Використання параметра `update` у Pydantic |
||||
|
|
||||
|
Тепер Ви можете створити копію наявної моделі за допомогою `.model_copy()`, і передати параметр `update` з `dict` , який містить дані для оновлення. |
||||
|
|
||||
|
/// info | Інформація |
||||
|
|
||||
|
У Pydantic v1 метод називався `.copy()`, він був застарілий (але все ще підтримується) у Pydantic v2, і був перейменований у `.model_copy()`. |
||||
|
|
||||
|
Приклади тут використовують `.copy()` для сумісності з Pydantic v1, але якщо Ви можете використовувати Pydantic v2 — Вам слід використовувати `.model_copy()` замість цього. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
Наприклад: `stored_item_model.model_copy(update=update_data)`: |
||||
|
|
||||
|
{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *} |
||||
|
|
||||
|
### Підсумок часткових оновлень |
||||
|
|
||||
|
У підсумку, щоб застосувати часткові оновлення, Ви: |
||||
|
|
||||
|
* (Опціонально) використовуєте `PATCH` замість `PUT`. |
||||
|
* Отримуєте збережені дані. |
||||
|
* Поміщаєте ці дані в модель Pydantic. |
||||
|
* Генеруєте `dict` без значень за замовчуванням з моделі введення (використовуючи `exclude_unset`). |
||||
|
* Таким чином Ви оновите лише ті значення, які були явно задані користувачем, замість того, щоб перезаписувати вже збережені значення значеннями за замовчуванням з вашої моделі. |
||||
|
* Створюєте копію збереженої моделі, оновлюючи її атрибути отриманими частковими оновленнями (використовуючи параметр `update`). |
||||
|
* Перетворюєте скопійовану модель на щось, що можна зберегти у вашу БД (наприклад, використовуючи `jsonable_encoder`). |
||||
|
* Це можна порівняти з повторним використанням методу `.model_dump()` моделі, але це гарантує (і перетворює) значення у типи даних, які можна перетворити на JSON, наприклад, `datetime` на `str`. |
||||
|
* Зберігаєте дані у вашу БД. |
||||
|
* Повертаєте оновлену модель. |
||||
|
|
||||
|
{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *} |
||||
|
|
||||
|
/// tip | Порада |
||||
|
|
||||
|
Насправді Ви можете використовувати цю саму техніку і з операцією HTTP `PUT`. |
||||
|
|
||||
|
Але приклад тут використовує `PATCH`, тому що він був створений саме для таких випадків. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
/// note | Примітка |
||||
|
|
||||
|
Зверніть увагу, що модель запиту все ще проходить валідацію. |
||||
|
|
||||
|
Тож, якщо Ви хочете отримувати часткові оновлення, які можуть не містити жодного атрибута, Вам потрібно мати модель, де всі атрибути позначені як необов’язкові (зі значеннями за замовчуванням або `None`). |
||||
|
|
||||
|
Щоб розрізняти моделі з усіма необов’язковими значеннями для **оновлення** і моделі з обов’язковими значеннями для **створення**, Ви можете скористатись ідеями, описаними у [Додаткові моделі](extra-models.md){.internal-link target=_blank}. |
||||
|
|
||||
|
/// |
@ -0,0 +1,358 @@ |
|||||
|
# Модель відповіді — Тип, що повертається |
||||
|
|
||||
|
Ви можете оголосити тип, який використовуватиметься у відповіді, за допомогою *анотації типу, що повертається* *функцією операцією шляху* (path operation) |
||||
|
|
||||
|
**Анотацію типу** можна вказати так само як і для вхідних **параметрів** функції: це можуть бути моделі Pydantic, списки (lists), словники (dictionaries), скалярні значення, як-от цілі числа (integers), булеві значення (booleans) тощо. |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} |
||||
|
|
||||
|
FastAPI використовуватиме цей тип, щоб: |
||||
|
|
||||
|
* **Перевірити правильність** повернених даних. |
||||
|
* Якщо дані не валідні (наприклад, відсутнє поле), це означає, що Ваш код додатку працює некоректно і не повертає те, що повинен. У такому випадку FastAPI поверне помилку сервера, замість того щоб віддати недопустимі дані. Так Ви та Ваші клієнти будете впевнені, що отримуєте очікувані дані у правильному форматі. |
||||
|
|
||||
|
* Додати **JSON Schema** відповіді до специфікації OpenAPI в *операціях шляху*. |
||||
|
* Це буде використано в **автоматичній документації**. |
||||
|
* А також інструментами, які автоматично генерують клієнтський код. |
||||
|
|
||||
|
Але найголовніше: |
||||
|
|
||||
|
* FastAPI **обмежить та відфільтрує** вихідні дані відповідно до типу, вказаного у відповіді. |
||||
|
* Це особливо важливо для **безпеки**. Деталі нижче. |
||||
|
|
||||
|
## Параметр `response_model` |
||||
|
|
||||
|
Іноді Вам потрібно або зручно повертати інші типи даних, ніж ті, що зазначені як тип відповіді. |
||||
|
|
||||
|
Наприклад, Ви можете **повертати словник** або об’єкт бази даних, але **оголосити модель Pydantic** як модель відповіді. Тоді модель Pydantic автоматично оброблятиме валідацію, документацію тощо. |
||||
|
|
||||
|
Якщо Ви додасте анотацію типу для повернення, редактор коду або mypy можуть поскаржитися, що функція повертає інший тип (наприклад, dict замість Item). |
||||
|
|
||||
|
У таких випадках можна скористатися параметром `response_model` в декораторі маршруту (наприклад, @app.get()). |
||||
|
|
||||
|
Параметр `response_model` працює з будь-яким *оператором шляху*: |
||||
|
|
||||
|
* `@app.get()` |
||||
|
* `@app.post()` |
||||
|
* `@app.put()` |
||||
|
* `@app.delete()` |
||||
|
* тощо. |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial001_py310.py hl[17,22,24:27] *} |
||||
|
|
||||
|
/// note | Примітка |
||||
|
|
||||
|
Зверніть увагу, що `response_model` є параметром методу-декоратора (`get`, `post`, тощо), а не *функцією операцією шляху* (path operation function), як це робиться з параметрами або тілом запиту. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
`response_model` приймає такий самий тип, який Ви б вказали для поля моделі Pydantic. Тобто це може бути як Pydantic-модель, так і, наприклад, `list` із моделей Pydantic — `List[Item]`. |
||||
|
|
||||
|
FastAPI використовуватиме `response_model` для створення документації, валідації даних та — найважливіше — **перетворення та фільтрації вихідних даних** згідно з оголошеним типом. |
||||
|
|
||||
|
/// tip | Порада |
||||
|
|
||||
|
Якщо у Вас увімкнено сувору перевірку типів у редакторі, mypy тощо, Ви можете оголосити тип повернення функції як `Any`. |
||||
|
|
||||
|
Таким чином, Ви повідомляєте редактору, що свідомо повертаєте будь-що. Але FastAPI усе одно виконуватиме створення документації, валідацію, фільтрацію тощо за допомогою параметра `response_model`. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
### Пріоритет `response_model` |
||||
|
|
||||
|
Якщо Ви вказуєте і тип повернення, і `response_model`, то FastAPI використовуватиме `response_model` з пріоритетом. |
||||
|
|
||||
|
Таким чином, Ви можете додати правильні анотації типів до ваших функцій, навіть якщо вони повертають тип, відмінний від `response_model`. Це буде корисно для редакторів коду та інструментів, таких як mypy. І при цьому FastAPI продовжить виконувати валідацію даних, генерувати документацію тощо на основі `response_model`. |
||||
|
|
||||
|
Ви також можете використати `response_model=None`, щоб вимкнути створення моделі відповіді для цієї *операції шляху*. Це може знадобитися, якщо Ви додаєте анотації типів до об'єктів, які не є допустимими полями Pydantic — приклад цього Ви побачите в одному з наступних розділів. |
||||
|
|
||||
|
## Повернути ті самі вхідні дані |
||||
|
|
||||
|
Тут ми оголошуємо модель `UserIn`, яка містить звичайний текстовий пароль: |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} |
||||
|
|
||||
|
/// info | Інформація |
||||
|
|
||||
|
Щоб використовувати `EmailStr`, спочатку встановіть <a href="https://github.com/JoshData/python-email-validator" class="external-link" target="_blank">`email-validator`</a>. |
||||
|
|
||||
|
Переконайтесь, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили пакет, наприклад: |
||||
|
|
||||
|
```console |
||||
|
$ pip install email-validator |
||||
|
``` |
||||
|
|
||||
|
or with: |
||||
|
|
||||
|
```console |
||||
|
$ pip install "pydantic[email]" |
||||
|
``` |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
І ми використовуємо цю модель, щоб оголосити і вхідні, і вихідні дані: |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial002_py310.py hl[16] *} |
||||
|
|
||||
|
Тепер, коли браузер створює користувача з паролем, API поверне той самий пароль у відповіді. |
||||
|
|
||||
|
У цьому випадку це може не бути проблемою, адже саме користувач надіслав пароль. |
||||
|
|
||||
|
Але якщо ми використаємо цю ж модель для іншої операції шляху, ми можемо випадково надіслати паролі наших користувачів кожному клієнту. |
||||
|
|
||||
|
/// danger | Обережно |
||||
|
|
||||
|
Ніколи не зберігайте пароль користувача у відкритому вигляді та не надсилайте його у відповіді, якщо тільки Ви не знаєте всі ризики і точно розумієте, що робите. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Додайте окрему вихідну модель |
||||
|
|
||||
|
Замість цього ми можемо створити вхідну модель з відкритим паролем і вихідну модель без нього: |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial003_py310.py hl[9,11,16] *} |
||||
|
|
||||
|
Тут, навіть якщо *функція операції шляху* повертає об'єкт користувача, який містить пароль: |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial003_py310.py hl[24] *} |
||||
|
|
||||
|
...ми оголосили `response_model` як нашу модель `UserOut`, яка не містить пароля: |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial003_py310.py hl[22] *} |
||||
|
|
||||
|
Таким чином, **FastAPI** автоматично відфільтрує всі дані, які не вказані у вихідній моделі (за допомогою Pydantic). |
||||
|
|
||||
|
### `response_model` або тип повернення |
||||
|
|
||||
|
У цьому випадку, оскільки дві моделі різні, якщо ми анотуємо тип повернення функції як `UserOut`, редактор і такі інструменти, як mypy, видадуть помилку, бо фактично ми повертаємо інший тип. |
||||
|
|
||||
|
Тому в цьому прикладі ми використовуємо параметр `response_model`, а не анотацію типу повернення. |
||||
|
|
||||
|
...але читайте далі, щоб дізнатися, як обійти це обмеження. |
||||
|
|
||||
|
## Тип повернення і фільтрація даних |
||||
|
|
||||
|
Продовжимо з попереднього прикладу. Ми хотіли **анотувати функцію одним типом**, але при цьому повертати з неї більше даних. |
||||
|
|
||||
|
Ми хочемо, щоб FastAPI продовжував **фільтрувати** ці дані за допомогою response_model. Тобто навіть якщо функція повертає більше інформації, у відповіді будуть лише ті поля, які вказані у response_model. |
||||
|
|
||||
|
У попередньому прикладі, оскільки класи були різні, нам довелося використовувати параметр `response_model`. Але це означає, що ми не отримуємо підтримки з боку редактора коду та інструментів перевірки типів щодо типу, який повертає функція. |
||||
|
|
||||
|
Проте в більшості випадків, коли нам потрібно зробити щось подібне, ми просто хочемо, щоб модель **відфільтрувала або прибрала** частину даних, як у цьому прикладі. |
||||
|
|
||||
|
У таких випадках ми можемо використати класи та спадкування, щоб скористатися **анотаціями типів** функцій — це дає кращу підтримку з боку редактора та інструментів типу mypy, і при цьому FastAPI продовжує виконувати **фільтрацію даних** у відповіді. |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *} |
||||
|
|
||||
|
Завдяки цьому ми отримуємо підтримку інструментів — від редакторів і mypy, оскільки цей код є коректним з точки зору типів, — але ми також отримуємо фільтрацію даних від FastAPI. |
||||
|
|
||||
|
Як це працює? Давайте розберемося. 🤓 |
||||
|
|
||||
|
### Типи та підтримка інструментів |
||||
|
|
||||
|
Спершу подивимось, як це бачать редактори, mypy та інші інструменти. |
||||
|
|
||||
|
`BaseUser` має базові поля. Потім `UserIn` успадковує `BaseUser` і додає поле `password`, отже, він матиме всі поля з обох моделей. |
||||
|
|
||||
|
Ми зазначаємо тип повернення функції як `BaseUser`, але фактично повертаємо екземпляр `UserIn`. |
||||
|
|
||||
|
Редактор, mypy та інші інструменти не скаржитимуться на це, тому що з точки зору типізації `UserIn` є підкласом `BaseUser`, а це означає, що він є `валідним` типом, коли очікується будь-що, що є `BaseUser`. |
||||
|
|
||||
|
### Фільтрація даних у FastAPI |
||||
|
|
||||
|
Тепер для FastAPI він бачить тип повернення і переконується, що те, що Ви повертаєте, містить **тільки** поля, які оголошені у цьому типі. |
||||
|
|
||||
|
FastAPI виконує кілька внутрішніх операцій з Pydantic, щоб гарантувати, що правила наслідування класів не застосовуються для фільтрації повернених даних, інакше Ви могли б повернути значно більше даних, ніж очікували. |
||||
|
|
||||
|
Таким чином, Ви отримуєте найкраще з двох світів: анотації типів **з підтримкою інструментів** і **фільтрацію даних**. |
||||
|
|
||||
|
## Подивитись у документації |
||||
|
|
||||
|
Коли Ви дивитесь автоматичну документацію, Ви можете побачити, що вхідна модель і вихідна модель мають власну JSON-схему: |
||||
|
|
||||
|
<img src="/img/tutorial/response-model/image01.png"> |
||||
|
|
||||
|
І обидві моделі використовуються для інтерактивної API-документації: |
||||
|
|
||||
|
<img src="/img/tutorial/response-model/image02.png"> |
||||
|
|
||||
|
## Інші анотації типів повернення |
||||
|
|
||||
|
Існують випадки, коли Ви повертаєте щось, що не є допустимим полем Pydantic, але анотуєте це у функції лише для того, щоб отримати підтримку від інструментів (редактора, mypy тощо). |
||||
|
|
||||
|
### Повернення Response напряму |
||||
|
|
||||
|
Найпоширенішим випадком буде [повернення Response напряму, як пояснюється пізніше у розширеній документації](../advanced/response-directly.md){.internal-link target=_blank}. |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial003_02.py hl[8,10:11] *} |
||||
|
|
||||
|
Цей простий випадок автоматично обробляється FastAPI, тому що анотація типу повернення — це клас (або підклас) `Response`. |
||||
|
|
||||
|
І інструменти також будуть задоволені, бо і `RedirectResponse`, і `JSONResponse` є підкласами `Response`, отже анотація типу коректна. |
||||
|
|
||||
|
### Анотація підкласу Response |
||||
|
|
||||
|
Також можна використовувати підклас `Response` у анотації типу: |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial003_03.py hl[8:9] *} |
||||
|
|
||||
|
Це теж працюватиме, бо `RedirectResponse` — підклас `Response`, і FastAPI автоматично обробить цей простий випадок. |
||||
|
|
||||
|
### Некоректні анотації типу повернення |
||||
|
|
||||
|
Але коли Ви повертаєте якийсь інший довільний об’єкт, що не є валідним типом Pydantic (наприклад, об’єкт бази даних), і анотуєте його так у функції, FastAPI спробує створити Pydantic модель відповіді на основі цієї анотації типу, і це завершиться помилкою. |
||||
|
|
||||
|
Те саме станеться, якщо Ви використовуєте <abbr title="Об'єднання (union) кількох типів означає: «будь-який з цих типів».">union</abbr> між різними типами, де один або більше не є валідними типами Pydantic, наприклад, це спричинить помилку 💥: |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} |
||||
|
|
||||
|
...це не працює, тому що тип анотації не є типом Pydantic і не є просто класом `Response` або його підкласом, а є об’єднанням (union) — або `Response`, або `dict`. |
||||
|
|
||||
|
### Відключення Моделі Відповіді |
||||
|
|
||||
|
Продовжуючи приклад вище, можливо, Ви не хочете використовувати стандартну валідацію даних, автоматичну документацію, фільтрацію тощо, які FastAPI виконує за замовчуванням. |
||||
|
|
||||
|
Але ви все одно можете залишити анотацію типу у функції, щоб зберегти підтримку з боку інструментів, таких як редактори коду або статичні перевірки типів (наприклад, mypy). |
||||
|
|
||||
|
У такому випадку ви можете вимкнути генерацію моделі відповіді, встановивши `response_model=None`: |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *} |
||||
|
|
||||
|
Це змусить FastAPI пропустити генерацію моделі відповіді, і таким чином Ви зможете використовувати будь-які анотації типів повернення без впливу на вашу FastAPI аплікацію. 🤓 |
||||
|
|
||||
|
## Параметри кодування моделі відповіді |
||||
|
|
||||
|
Ваша модель відповіді може мати значення за замовчуванням, наприклад: |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial004_py310.py hl[9,11:12] *} |
||||
|
|
||||
|
* `description: Union[str, None] = None` (або `str | None = None` у Python 3.10) має значення за замовчуванням `None`. |
||||
|
* `tax: float = 10.5` має значення за замовчуванням `10.5`. |
||||
|
* `tags: List[str] = []` має значення за замовчуванням порожній список: `[]`. |
||||
|
|
||||
|
Але Ви можете захотіти не включати їх у результат, якщо вони фактично не були збережені. |
||||
|
|
||||
|
Наприклад, якщо у Вас є моделі з багатьма необов’язковими атрибутами у NoSQL базі даних, але Ви не хочете відправляти дуже довгі JSON-відповіді, повні значень за замовчуванням. |
||||
|
|
||||
|
### Використовуйте параметр `response_model_exclude_unset` |
||||
|
|
||||
|
Ви можете встановити параметр декоратора шляху `response_model_exclude_unset=True`: |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial004_py310.py hl[22] *} |
||||
|
|
||||
|
і ці значення за замовчуванням не будуть включені у відповідь, тільки фактично встановлені значення. |
||||
|
|
||||
|
Отже, якщо Ви надішлете запит до цього оператора шляху для елемента з item_id `foo`, відповідь (без включення значень за замовчуванням) буде: |
||||
|
|
||||
|
```JSON |
||||
|
{ |
||||
|
"name": "Foo", |
||||
|
"price": 50.2 |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
/// info | Інформація |
||||
|
|
||||
|
У Pydantic версії 1 метод називався `.dict()`, він був застарілий (але ще підтримується) у Pydantic версії 2 і перейменований у `.model_dump()`. |
||||
|
|
||||
|
Приклади тут використовують `.dict()` для сумісності з Pydantic v1, але Вам слід використовувати `.model_dump()`, якщо Ви можете використовувати Pydantic v2. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
/// info | Інформація |
||||
|
|
||||
|
FastAPI використовує `.dict()` моделі Pydantic з <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">параметром `exclude_unset`</a>, щоб досягти цього. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
/// info | Інформація |
||||
|
|
||||
|
Ви також можете використовувати: |
||||
|
|
||||
|
* `response_model_exclude_defaults=True` |
||||
|
* `response_model_exclude_none=True` |
||||
|
|
||||
|
як описано в <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">документації Pydantic</a> for `exclude_defaults` та `exclude_none`. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
#### Дані зі значеннями для полів із типовими значеннями |
||||
|
|
||||
|
Але якщо Ваші дані мають значення для полів моделі з типовими значеннями, як у елемента з item_id `bar`: |
||||
|
|
||||
|
```Python hl_lines="3 5" |
||||
|
{ |
||||
|
"name": "Bar", |
||||
|
"description": "The bartenders", |
||||
|
"price": 62, |
||||
|
"tax": 20.2 |
||||
|
} |
||||
|
``` |
||||
|
вони будуть включені у відповідь. |
||||
|
|
||||
|
#### Дані з тими самими значеннями, що й типові |
||||
|
|
||||
|
Якщо дані мають ті самі значення, що й типові, як у елемента з item_id `baz`: |
||||
|
|
||||
|
```Python hl_lines="3 5-6" |
||||
|
{ |
||||
|
"name": "Baz", |
||||
|
"description": None, |
||||
|
"price": 50.2, |
||||
|
"tax": 10.5, |
||||
|
"tags": [] |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
FastAPI достатньо розумний (насправді, Pydantic достатньо розумний), щоб зрозуміти, що, хоча `description`, `tax` і `tags` мають ті самі значення, що й типові, вони були встановлені явно (а не взяті як значення за замовчуванням). |
||||
|
|
||||
|
Отже, вони будуть включені у JSON-відповідь. |
||||
|
|
||||
|
/// tip | Порада |
||||
|
|
||||
|
Зверніть увагу, що типові значення можуть бути будь-якими, не лише `None`. |
||||
|
|
||||
|
Це може бути list (`[]`), `float` 10.5 тощо. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
### `response_model_include` та `response_model_exclude` |
||||
|
|
||||
|
Ви також можете використовувати параметри *декоратора операції шляху* `response_model_include` та `response_model_exclude`. |
||||
|
|
||||
|
Вони приймають `set` (множину) рядків (`str`) з іменами атрибутів, які потрібно включити (пропускаючи інші) або виключити (включаючи інші). |
||||
|
|
||||
|
Це можна використовувати як швидкий спосіб, якщо у Вас є лише одна модель Pydantic і Ви хочете видалити деякі дані з виводу. |
||||
|
|
||||
|
/// tip | Порада |
||||
|
|
||||
|
Але все ж рекомендується використовувати описані вище підходи, із застосуванням кількох класів, замість цих параметрів. |
||||
|
|
||||
|
|
||||
|
Це тому, що JSON Schema, який генерується у вашому OpenAPI додатку (і в документації), все одно буде відповідати повній моделі, навіть якщо Ви використовуєте `response_model_include` або `response_model_exclude` для виключення деяких атрибутів. |
||||
|
|
||||
|
Це також стосується `response_model_by_alias`, який працює подібним чином. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial005_py310.py hl[29,35] *} |
||||
|
|
||||
|
/// tip | Порада |
||||
|
|
||||
|
Синтаксис `{"name", "description"}` створює `set` з цими двома значеннями. |
||||
|
|
||||
|
Він еквівалентний `set(["name", "description"])`. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
#### Використання `list` замість `set` |
||||
|
|
||||
|
Якщо Ви забудете використати `set` і натомість застосуєте `list` або `tuple`, FastAPI все одно перетворить це на `set`, і все працюватиме правильно: |
||||
|
|
||||
|
{* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *} |
||||
|
|
||||
|
## Підсумок |
||||
|
|
||||
|
Використовуйте параметр `response_model` *декоратора операції шляху*, щоб визначати моделі відповіді, особливо щоб гарантувати фільтрацію приватних даних. |
||||
|
|
||||
|
Використовуйте `response_model_exclude_unset`, щоб повертати лише явно встановлені значення. |
@ -0,0 +1,104 @@ |
|||||
|
# Безпека |
||||
|
|
||||
|
Існує багато способів реалізувати безпеку, автентифікацію та авторизацію. |
||||
|
|
||||
|
Це зазвичай складна і "непроста" тема. |
||||
|
|
||||
|
У багатьох фреймворках і системах забезпечення безпеки та автентифікації займає величезну частину зусиль і коду (іноді — понад 50% всього написаного коду). |
||||
|
|
||||
|
**FastAPI** надає кілька інструментів, які допоможуть Вам впоратися з **безпекою** легко, швидко, стандартним способом, без необхідності вивчати всі специфікації безпеки. |
||||
|
|
||||
|
Але спочатку — кілька коротких понять. |
||||
|
|
||||
|
## Поспішаєте? |
||||
|
|
||||
|
Якщо Вам не цікаві всі ці терміни й просто потрібно *швидко* додати автентифікацію за логіном і паролем — переходьте до наступних розділів. |
||||
|
|
||||
|
## OAuth2 |
||||
|
|
||||
|
OAuth2 — це специфікація, що описує кілька способів обробки автентифікації та авторизації. |
||||
|
|
||||
|
Це досить об'ємна специфікація, яка охоплює складні випадки використання. |
||||
|
|
||||
|
Вона включає способи автентифікації через "третю сторону". |
||||
|
|
||||
|
Саме це лежить в основі "входу через Google, Facebook, X (Twitter), GitHub" тощо. |
||||
|
|
||||
|
### OAuth 1 |
||||
|
|
||||
|
Раніше існував OAuth 1, який значно відрізняється від OAuth2 і є складнішим, оскільки містив специфікації для шифрування комунікацій. |
||||
|
|
||||
|
Зараз майже не використовується. |
||||
|
|
||||
|
OAuth2 не вказує, як саме шифрувати з'єднання — воно очікує, що ваш застосунок працює через HTTPS. |
||||
|
|
||||
|
/// tip | Порада |
||||
|
|
||||
|
У розділі про **деплой** Ви побачите, як налаштувати HTTPS безкоштовно з Traefik та Let's Encrypt. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## OpenID Connect |
||||
|
|
||||
|
OpenID Connect — ще одна специфікація, побудована на основі **OAuth2**. |
||||
|
|
||||
|
Вона розширює OAuth2, уточнюючи деякі неоднозначності для досягнення кращої сумісності. |
||||
|
|
||||
|
Наприклад, вхід через Google використовує OpenID Connect (який базується на OAuth2). |
||||
|
|
||||
|
Але вхід через Facebook — ні. Він має власну реалізацію на базі OAuth2. |
||||
|
|
||||
|
### OpenID (не "OpenID Connect") |
||||
|
|
||||
|
Існувала також специфікація "OpenID", яка намагалася розвʼязати ті самі задачі, що й **OpenID Connect**, але не базувалась на OAuth2. |
||||
|
|
||||
|
Це була зовсім інша система, і сьогодні вона майже не використовується. |
||||
|
|
||||
|
## OpenAPI |
||||
|
|
||||
|
OpenAPI (раніше Swagger) — це специфікація для побудови API (тепер під егідою Linux Foundation). |
||||
|
|
||||
|
**FastAPI** базується на **OpenAPI**. |
||||
|
|
||||
|
Завдяки цьому Ви отримуєте автоматичну інтерактивну документацію, генерацію коду та багато іншого. |
||||
|
|
||||
|
OpenAPI дозволяє описувати різні "схеми" безпеки. |
||||
|
|
||||
|
Використовуючи їх, Ви можете скористатися всіма цими інструментами, що базуються на стандартах, зокрема інтерактивними системами документації. |
||||
|
|
||||
|
OpenAPI визначає такі схеми безпеки: |
||||
|
|
||||
|
* `apiKey`: специфічний для застосунку ключ, який може передаватися через: |
||||
|
* Параметр запиту. |
||||
|
* Заголовок. |
||||
|
* Cookie. |
||||
|
* `http`: стандартні методи HTTP-автентифікації, включаючи: |
||||
|
* `bearer`: заголовок `Authorization` зі значенням `Bearer` та токеном. Це успадковано з OAuth2. |
||||
|
* HTTP Basic автентифікація |
||||
|
* HTTP Digest, тощо. |
||||
|
* `oauth2`: усі способи обробки безпеки за допомогою OAuth2 (так звані «потоки»). |
||||
|
* Деякі з цих потоків підходять для створення власного провайдера автентифікації OAuth 2.0 (наприклад, Google, Facebook, X (Twitter), GitHub тощо): |
||||
|
* `implicit`— неявний |
||||
|
* `clientCredentials`— облікові дані клієнта |
||||
|
* `authorizationCode` — код авторизації |
||||
|
* Але є один окремий «потік», який ідеально підходить для реалізації автентифікації всередині одного додатку: |
||||
|
* `password`: у наступних розділах буде приклад використання цього потоку. |
||||
|
* `openIdConnect`: дозволяє автоматично виявляти параметри автентифікації OAuth2. |
||||
|
* Це автоматичне виявлення визначається у специфікації OpenID Connect. |
||||
|
|
||||
|
|
||||
|
/// tip | Порада |
||||
|
|
||||
|
Інтеграція інших провайдерів автентифікації/авторизації, таких як Google, Facebook, X (Twitter), GitHub тощо — також можлива і відносно проста. |
||||
|
|
||||
|
Найскладніше — це створити власного провайдера автентифікації/авторизації, як Google чи Facebook. Але **FastAPI** надає Вам інструменти, щоб зробити це легко, беручи на себе важку частину роботи. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## Інструменти **FastAPI** |
||||
|
|
||||
|
FastAPI надає кілька інструментів для кожної з описаних схем безпеки в модулі `fastapi.security`, які спрощують використання цих механізмів захисту. |
||||
|
|
||||
|
У наступних розділах Ви побачите, як додати безпеку до свого API за допомогою цих інструментів **FastAPI**. |
||||
|
|
||||
|
А також побачите, як вона автоматично інтегрується в інтерактивну документацію вашого API. |
@ -0,0 +1,156 @@ |
|||||
|
from typing import Union |
||||
|
|
||||
|
from fastapi import FastAPI, Form |
||||
|
from fastapi.testclient import TestClient |
||||
|
from pydantic import BaseModel |
||||
|
from typing_extensions import Annotated |
||||
|
|
||||
|
app = FastAPI() |
||||
|
|
||||
|
|
||||
|
class UserForm(BaseModel): |
||||
|
name: str |
||||
|
email: str |
||||
|
|
||||
|
|
||||
|
class CompanyForm(BaseModel): |
||||
|
company_name: str |
||||
|
industry: str |
||||
|
|
||||
|
|
||||
|
@app.post("/form-union/") |
||||
|
def post_union_form(data: Annotated[Union[UserForm, CompanyForm], Form()]): |
||||
|
return {"received": data} |
||||
|
|
||||
|
|
||||
|
client = TestClient(app) |
||||
|
|
||||
|
|
||||
|
def test_post_user_form(): |
||||
|
response = client.post( |
||||
|
"/form-union/", data={"name": "John Doe", "email": "john@example.com"} |
||||
|
) |
||||
|
assert response.status_code == 200, response.text |
||||
|
assert response.json() == { |
||||
|
"received": {"name": "John Doe", "email": "john@example.com"} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
def test_post_company_form(): |
||||
|
response = client.post( |
||||
|
"/form-union/", data={"company_name": "Tech Corp", "industry": "Technology"} |
||||
|
) |
||||
|
assert response.status_code == 200, response.text |
||||
|
assert response.json() == { |
||||
|
"received": {"company_name": "Tech Corp", "industry": "Technology"} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
def test_invalid_form_data(): |
||||
|
response = client.post( |
||||
|
"/form-union/", |
||||
|
data={"name": "John", "company_name": "Tech Corp"}, |
||||
|
) |
||||
|
assert response.status_code == 422, response.text |
||||
|
|
||||
|
|
||||
|
def test_empty_form(): |
||||
|
response = client.post("/form-union/") |
||||
|
assert response.status_code == 422, response.text |
||||
|
|
||||
|
|
||||
|
def test_openapi_schema(): |
||||
|
response = client.get("/openapi.json") |
||||
|
assert response.status_code == 200, response.text |
||||
|
|
||||
|
assert response.json() == { |
||||
|
"openapi": "3.1.0", |
||||
|
"info": {"title": "FastAPI", "version": "0.1.0"}, |
||||
|
"paths": { |
||||
|
"/form-union/": { |
||||
|
"post": { |
||||
|
"summary": "Post Union Form", |
||||
|
"operationId": "post_union_form_form_union__post", |
||||
|
"requestBody": { |
||||
|
"content": { |
||||
|
"application/x-www-form-urlencoded": { |
||||
|
"schema": { |
||||
|
"anyOf": [ |
||||
|
{"$ref": "#/components/schemas/UserForm"}, |
||||
|
{"$ref": "#/components/schemas/CompanyForm"}, |
||||
|
], |
||||
|
"title": "Data", |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
"required": True, |
||||
|
}, |
||||
|
"responses": { |
||||
|
"200": { |
||||
|
"description": "Successful Response", |
||||
|
"content": {"application/json": {"schema": {}}}, |
||||
|
}, |
||||
|
"422": { |
||||
|
"description": "Validation Error", |
||||
|
"content": { |
||||
|
"application/json": { |
||||
|
"schema": { |
||||
|
"$ref": "#/components/schemas/HTTPValidationError" |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
"components": { |
||||
|
"schemas": { |
||||
|
"CompanyForm": { |
||||
|
"properties": { |
||||
|
"company_name": {"type": "string", "title": "Company Name"}, |
||||
|
"industry": {"type": "string", "title": "Industry"}, |
||||
|
}, |
||||
|
"type": "object", |
||||
|
"required": ["company_name", "industry"], |
||||
|
"title": "CompanyForm", |
||||
|
}, |
||||
|
"HTTPValidationError": { |
||||
|
"properties": { |
||||
|
"detail": { |
||||
|
"items": {"$ref": "#/components/schemas/ValidationError"}, |
||||
|
"type": "array", |
||||
|
"title": "Detail", |
||||
|
} |
||||
|
}, |
||||
|
"type": "object", |
||||
|
"title": "HTTPValidationError", |
||||
|
}, |
||||
|
"UserForm": { |
||||
|
"properties": { |
||||
|
"name": {"type": "string", "title": "Name"}, |
||||
|
"email": {"type": "string", "title": "Email"}, |
||||
|
}, |
||||
|
"type": "object", |
||||
|
"required": ["name", "email"], |
||||
|
"title": "UserForm", |
||||
|
}, |
||||
|
"ValidationError": { |
||||
|
"properties": { |
||||
|
"loc": { |
||||
|
"items": { |
||||
|
"anyOf": [{"type": "string"}, {"type": "integer"}] |
||||
|
}, |
||||
|
"type": "array", |
||||
|
"title": "Location", |
||||
|
}, |
||||
|
"msg": {"type": "string", "title": "Message"}, |
||||
|
"type": {"type": "string", "title": "Error Type"}, |
||||
|
}, |
||||
|
"type": "object", |
||||
|
"required": ["loc", "msg", "type"], |
||||
|
"title": "ValidationError", |
||||
|
}, |
||||
|
} |
||||
|
}, |
||||
|
} |
Loading…
Reference in new issue