Browse Source

🔄 Merge branch 'master' into pr/phy1729/9555

pull/9555/head
Sebastián Ramírez 8 months ago
parent
commit
4429aaadef
  1. 3
      README.md
  2. 3
      docs/en/data/sponsors.yml
  3. 1
      docs/en/data/sponsors_badge.yml
  4. 460
      docs/en/data/topic_repos.yml
  5. 8
      docs/en/docs/advanced/behind-a-proxy.md
  6. BIN
      docs/en/docs/img/sponsors/greptile-banner.png
  7. BIN
      docs/en/docs/img/sponsors/greptile.png
  8. 2
      docs/en/docs/index.md
  9. 42
      docs/en/docs/release-notes.md
  10. 2
      docs/en/docs/tutorial/sql-databases.md
  11. 20
      docs/en/docs/virtual-environments.md
  12. 6
      docs/en/overrides/main.html
  13. 2
      fastapi/__init__.py
  14. 23
      fastapi/_compat/v2.py
  15. 7
      fastapi/applications.py
  16. 25
      fastapi/dependencies/utils.py
  17. 12
      fastapi/encoders.py
  18. 12
      fastapi/utils.py
  19. 24
      tests/test_compat.py
  20. 7
      tests/test_computed_fields.py
  21. 2
      tests/test_fastapi_cli.py
  22. 35
      tests/test_form_default.py
  23. 47
      tests/test_forms_single_model.py
  24. 15
      tests/test_jsonable_encoder.py
  25. 30
      tests/test_optional_file_list.py
  26. 111
      tests/test_query_cookie_header_model_extra_params.py
  27. 76
      tests/test_request_param_model_by_alias.py
  28. 92
      tests/test_schema_compat_pydantic_v2.py
  29. 2
      tests/test_tutorial/test_header_param_models/test_tutorial003.py

3
README.md

@ -40,7 +40,7 @@ The key features are:
* **Robust**: Get production-ready code. With automatic interactive documentation. * **Robust**: Get production-ready code. With automatic interactive documentation.
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>. * **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>* estimation based on tests on an internal development team, building production applications.</small> <small>* estimation based on tests conducted by an internal development team, building production applications.</small>
## Sponsors ## Sponsors
@ -61,6 +61,7 @@ The key features are:
<a href="https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source" target="_blank" title="The Gold Standard in Retail Account Linking"><img src="https://fastapi.tiangolo.com/img/sponsors/subtotal.svg"></a> <a href="https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source" target="_blank" title="The Gold Standard in Retail Account Linking"><img src="https://fastapi.tiangolo.com/img/sponsors/subtotal.svg"></a>
<a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" target="_blank" title="Deploy enterprise applications at startup speed"><img src="https://fastapi.tiangolo.com/img/sponsors/railway.png"></a> <a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" target="_blank" title="Deploy enterprise applications at startup speed"><img src="https://fastapi.tiangolo.com/img/sponsors/railway.png"></a>
<a href="https://serpapi.com/?utm_source=fastapi_website" target="_blank" title="SerpApi: Web Search API"><img src="https://fastapi.tiangolo.com/img/sponsors/serpapi.png"></a> <a href="https://serpapi.com/?utm_source=fastapi_website" target="_blank" title="SerpApi: Web Search API"><img src="https://fastapi.tiangolo.com/img/sponsors/serpapi.png"></a>
<a href="https://www.greptile.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=fastapi_sponsor_page" target="_blank" title="Greptile: The AI Code Reviewer"><img src="https://fastapi.tiangolo.com/img/sponsors/greptile.png"></a>
<a href="https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display" target="_blank" title="Pay as you go for market data"><img src="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a> <a href="https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display" target="_blank" title="Pay as you go for market data"><img src="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a>
<a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" target="_blank" title="SDKs for your API | Speakeasy"><img src="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a> <a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" target="_blank" title="SDKs for your API | Speakeasy"><img src="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a>
<a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a> <a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a>

3
docs/en/data/sponsors.yml

@ -33,6 +33,9 @@ gold:
- url: https://serpapi.com/?utm_source=fastapi_website - url: https://serpapi.com/?utm_source=fastapi_website
title: "SerpApi: Web Search API" title: "SerpApi: Web Search API"
img: https://fastapi.tiangolo.com/img/sponsors/serpapi.png img: https://fastapi.tiangolo.com/img/sponsors/serpapi.png
- url: https://www.greptile.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=fastapi_sponsor_page
title: "Greptile: The AI Code Reviewer"
img: https://fastapi.tiangolo.com/img/sponsors/greptile.png
silver: silver:
- url: https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display - url: https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display
title: Pay as you go for market data title: Pay as you go for market data

1
docs/en/data/sponsors_badge.yml

@ -47,3 +47,4 @@ logins:
- railwayapp - railwayapp
- subtotal - subtotal
- requestly - requestly
- greptileai

460
docs/en/data/topic_repos.yml

@ -1,368 +1,388 @@
- 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: 38779 stars: 39475
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: 32726 stars: 33090
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: 21779 stars: 21798
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: 20028 stars: 20258
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: 17038 stars: 17212
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: 14786 stars: 15145
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: 13968 stars: 14644
owner_login: zhanymkanov owner_login: zhanymkanov
owner_html_url: https://github.com/zhanymkanov owner_html_url: https://github.com/zhanymkanov
- name: machine-learning-zoomcamp - name: machine-learning-zoomcamp
html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp
stars: 12171 stars: 12320
owner_login: DataTalksClub owner_login: DataTalksClub
owner_html_url: https://github.com/DataTalksClub owner_html_url: https://github.com/DataTalksClub
- name: fastapi_mcp - name: fastapi_mcp
html_url: https://github.com/tadata-org/fastapi_mcp html_url: https://github.com/tadata-org/fastapi_mcp
stars: 10976 stars: 11174
owner_login: tadata-org owner_login: tadata-org
owner_html_url: https://github.com/tadata-org owner_html_url: https://github.com/tadata-org
- name: awesome-fastapi
html_url: https://github.com/mjhea0/awesome-fastapi
stars: 10618
owner_login: mjhea0
owner_html_url: https://github.com/mjhea0
- name: SurfSense - name: SurfSense
html_url: https://github.com/MODSetter/SurfSense html_url: https://github.com/MODSetter/SurfSense
stars: 10243 stars: 10858
owner_login: MODSetter owner_login: MODSetter
owner_html_url: https://github.com/MODSetter owner_html_url: https://github.com/MODSetter
- name: awesome-fastapi
html_url: https://github.com/mjhea0/awesome-fastapi
stars: 10758
owner_login: mjhea0
owner_html_url: https://github.com/mjhea0
- name: XHS-Downloader - name: XHS-Downloader
html_url: https://github.com/JoeanAmier/XHS-Downloader html_url: https://github.com/JoeanAmier/XHS-Downloader
stars: 9062 stars: 9313
owner_login: JoeanAmier owner_login: JoeanAmier
owner_html_url: https://github.com/JoeanAmier owner_html_url: https://github.com/JoeanAmier
- name: FastUI - name: FastUI
html_url: https://github.com/pydantic/FastUI html_url: https://github.com/pydantic/FastUI
stars: 8892 stars: 8915
owner_login: pydantic owner_login: pydantic
owner_html_url: https://github.com/pydantic owner_html_url: https://github.com/pydantic
- name: polar - name: polar
html_url: https://github.com/polarsource/polar html_url: https://github.com/polarsource/polar
stars: 8084 stars: 8339
owner_login: polarsource owner_login: polarsource
owner_html_url: https://github.com/polarsource owner_html_url: https://github.com/polarsource
- name: FileCodeBox - name: FileCodeBox
html_url: https://github.com/vastsa/FileCodeBox html_url: https://github.com/vastsa/FileCodeBox
stars: 7494 stars: 7721
owner_login: vastsa owner_login: vastsa
owner_html_url: https://github.com/vastsa owner_html_url: https://github.com/vastsa
- name: nonebot2 - name: nonebot2
html_url: https://github.com/nonebot/nonebot2 html_url: https://github.com/nonebot/nonebot2
stars: 7128 stars: 7170
owner_login: nonebot owner_login: nonebot
owner_html_url: https://github.com/nonebot owner_html_url: https://github.com/nonebot
- name: hatchet - name: hatchet
html_url: https://github.com/hatchet-dev/hatchet html_url: https://github.com/hatchet-dev/hatchet
stars: 6155 stars: 6253
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: 5754
owner_login: serge-chat
owner_html_url: https://github.com/serge-chat
- 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: 5683 stars: 5849
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: serge
html_url: https://github.com/serge-chat/serge
stars: 5756
owner_login: serge-chat
owner_html_url: https://github.com/serge-chat
- name: strawberry - name: strawberry
html_url: https://github.com/strawberry-graphql/strawberry html_url: https://github.com/strawberry-graphql/strawberry
stars: 4452 stars: 4569
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 - name: chatgpt-web-share
html_url: https://github.com/chatpire/chatgpt-web-share html_url: https://github.com/chatpire/chatgpt-web-share
stars: 4296 stars: 4294
owner_login: chatpire owner_login: chatpire
owner_html_url: https://github.com/chatpire owner_html_url: https://github.com/chatpire
- name: poem - name: poem
html_url: https://github.com/poem-web/poem html_url: https://github.com/poem-web/poem
stars: 4235 stars: 4276
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: dynaconf - name: dynaconf
html_url: https://github.com/dynaconf/dynaconf html_url: https://github.com/dynaconf/dynaconf
stars: 4174 stars: 4202
owner_login: dynaconf owner_login: dynaconf
owner_html_url: https://github.com/dynaconf owner_html_url: https://github.com/dynaconf
- 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: 4094 stars: 4093
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: Kokoro-FastAPI - name: Kokoro-FastAPI
html_url: https://github.com/remsky/Kokoro-FastAPI html_url: https://github.com/remsky/Kokoro-FastAPI
stars: 3875 stars: 4019
owner_login: remsky owner_login: remsky
owner_html_url: https://github.com/remsky owner_html_url: https://github.com/remsky
- name: logfire - name: logfire
html_url: https://github.com/pydantic/logfire html_url: https://github.com/pydantic/logfire
stars: 3717 stars: 3805
owner_login: pydantic owner_login: pydantic
owner_html_url: https://github.com/pydantic owner_html_url: https://github.com/pydantic
- name: LitServe - name: LitServe
html_url: https://github.com/Lightning-AI/LitServe html_url: https://github.com/Lightning-AI/LitServe
stars: 3615 stars: 3719
owner_login: Lightning-AI owner_login: Lightning-AI
owner_html_url: https://github.com/Lightning-AI owner_html_url: https://github.com/Lightning-AI
- name: fastapi-admin
html_url: https://github.com/fastapi-admin/fastapi-admin
stars: 3632
owner_login: fastapi-admin
owner_html_url: https://github.com/fastapi-admin
- name: datamodel-code-generator - name: datamodel-code-generator
html_url: https://github.com/koxudaxi/datamodel-code-generator html_url: https://github.com/koxudaxi/datamodel-code-generator
stars: 3554 stars: 3609
owner_login: koxudaxi owner_login: koxudaxi
owner_html_url: https://github.com/koxudaxi owner_html_url: https://github.com/koxudaxi
- name: huma - name: huma
html_url: https://github.com/danielgtaylor/huma html_url: https://github.com/danielgtaylor/huma
stars: 3521 stars: 3603
owner_login: danielgtaylor owner_login: danielgtaylor
owner_html_url: https://github.com/danielgtaylor owner_html_url: https://github.com/danielgtaylor
- name: fastapi-admin
html_url: https://github.com/fastapi-admin/fastapi-admin
stars: 3497
owner_login: fastapi-admin
owner_html_url: https://github.com/fastapi-admin
- name: farfalle - name: farfalle
html_url: https://github.com/rashadphz/farfalle html_url: https://github.com/rashadphz/farfalle
stars: 3476 stars: 3490
owner_login: rashadphz owner_login: rashadphz
owner_html_url: https://github.com/rashadphz owner_html_url: https://github.com/rashadphz
- name: tracecat - name: tracecat
html_url: https://github.com/TracecatHQ/tracecat html_url: https://github.com/TracecatHQ/tracecat
stars: 3310 stars: 3379
owner_login: TracecatHQ owner_login: TracecatHQ
owner_html_url: https://github.com/TracecatHQ owner_html_url: https://github.com/TracecatHQ
- name: opyrator - name: opyrator
html_url: https://github.com/ml-tooling/opyrator html_url: https://github.com/ml-tooling/opyrator
stars: 3134 stars: 3135
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: docarray - name: docarray
html_url: https://github.com/docarray/docarray html_url: https://github.com/docarray/docarray
stars: 3108 stars: 3114
owner_login: docarray owner_login: docarray
owner_html_url: https://github.com/docarray owner_html_url: https://github.com/docarray
- name: devpush
html_url: https://github.com/hunvreus/devpush
stars: 3097
owner_login: hunvreus
owner_html_url: https://github.com/hunvreus
- name: fastapi-realworld-example-app - 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: 2945 stars: 3050
owner_login: nsidnev owner_login: nsidnev
owner_html_url: https://github.com/nsidnev owner_html_url: https://github.com/nsidnev
- name: uvicorn-gunicorn-fastapi-docker - name: uvicorn-gunicorn-fastapi-docker
html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker
stars: 2809 stars: 2911
owner_login: tiangolo owner_login: tiangolo
owner_html_url: https://github.com/tiangolo owner_html_url: https://github.com/tiangolo
- name: devpush
html_url: https://github.com/hunvreus/devpush
stars: 2784
owner_login: hunvreus
owner_html_url: https://github.com/hunvreus
- name: mcp-context-forge - name: mcp-context-forge
html_url: https://github.com/IBM/mcp-context-forge html_url: https://github.com/IBM/mcp-context-forge
stars: 2763 stars: 2899
owner_login: IBM owner_login: IBM
owner_html_url: https://github.com/IBM owner_html_url: https://github.com/IBM
- 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: 2630 stars: 2648
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: fastapi-react
html_url: https://github.com/Buuntu/fastapi-react
stars: 2464
owner_login: 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: 2453 stars: 2637
owner_login: s3rius owner_login: s3rius
owner_html_url: https://github.com/s3rius owner_html_url: https://github.com/s3rius
- name: RasaGPT - name: YC-Killer
html_url: https://github.com/paulpierre/RasaGPT html_url: https://github.com/sahibzada-allahyar/YC-Killer
stars: 2444 stars: 2599
owner_login: paulpierre owner_login: sahibzada-allahyar
owner_html_url: https://github.com/paulpierre owner_html_url: https://github.com/sahibzada-allahyar
- name: fastapi-react
html_url: https://github.com/Buuntu/fastapi-react
stars: 2569
owner_login: Buuntu
owner_html_url: https://github.com/Buuntu
- name: Yuxi-Know
html_url: https://github.com/xerrors/Yuxi-Know
stars: 2563
owner_login: xerrors
owner_html_url: https://github.com/xerrors
- name: sqladmin - name: sqladmin
html_url: https://github.com/aminalaee/sqladmin html_url: https://github.com/aminalaee/sqladmin
stars: 2423 stars: 2558
owner_login: aminalaee owner_login: aminalaee
owner_html_url: https://github.com/aminalaee owner_html_url: https://github.com/aminalaee
- name: nextpy - name: RasaGPT
html_url: https://github.com/dot-agent/nextpy html_url: https://github.com/paulpierre/RasaGPT
stars: 2325 stars: 2451
owner_login: dot-agent owner_login: paulpierre
owner_html_url: https://github.com/dot-agent owner_html_url: https://github.com/paulpierre
- name: supabase-py - name: supabase-py
html_url: https://github.com/supabase/supabase-py html_url: https://github.com/supabase/supabase-py
stars: 2292 stars: 2344
owner_login: supabase owner_login: supabase
owner_html_url: https://github.com/supabase owner_html_url: https://github.com/supabase
- name: nextpy
html_url: https://github.com/dot-agent/nextpy
stars: 2335
owner_login: dot-agent
owner_html_url: https://github.com/dot-agent
- name: fastapi-utils
html_url: https://github.com/fastapiutils/fastapi-utils
stars: 2291
owner_login: fastapiutils
owner_html_url: https://github.com/fastapiutils
- 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: 2214 stars: 2220
owner_login: codingforentrepreneurs owner_login: codingforentrepreneurs
owner_html_url: https://github.com/codingforentrepreneurs owner_html_url: https://github.com/codingforentrepreneurs
- name: Yuxi-Know
html_url: https://github.com/xerrors/Yuxi-Know
stars: 2212
owner_login: xerrors
owner_html_url: https://github.com/xerrors
- name: langserve - name: langserve
html_url: https://github.com/langchain-ai/langserve html_url: https://github.com/langchain-ai/langserve
stars: 2191 stars: 2215
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
html_url: https://github.com/fastapiutils/fastapi-utils
stars: 2185
owner_login: fastapiutils
owner_html_url: https://github.com/fastapiutils
- name: solara - name: solara
html_url: https://github.com/widgetti/solara html_url: https://github.com/widgetti/solara
stars: 2111 stars: 2122
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: 2011 stars: 2029
owner_login: Kludex owner_login: Kludex
owner_html_url: https://github.com/Kludex owner_html_url: https://github.com/Kludex
- name: agentkit - name: agentkit
html_url: https://github.com/BCG-X-Official/agentkit html_url: https://github.com/BCG-X-Official/agentkit
stars: 1826 stars: 1912
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: python-week-2022
html_url: https://github.com/rochacbruno/python-week-2022
stars: 1815
owner_login: rochacbruno
owner_html_url: https://github.com/rochacbruno
- name: manage-fastapi - name: manage-fastapi
html_url: https://github.com/ycd/manage-fastapi html_url: https://github.com/ycd/manage-fastapi
stars: 1787 stars: 1885
owner_login: ycd owner_login: ycd
owner_html_url: https://github.com/ycd owner_html_url: https://github.com/ycd
- name: ormar
html_url: https://github.com/collerek/ormar
stars: 1780
owner_login: collerek
owner_html_url: https://github.com/collerek
- name: vue-fastapi-admin
html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin
stars: 1758
owner_login: mizhexiaoxiao
owner_html_url: https://github.com/mizhexiaoxiao
- 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: 1731 stars: 1862
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: piccolo - name: piccolo
html_url: https://github.com/piccolo-orm/piccolo html_url: https://github.com/piccolo-orm/piccolo
stars: 1711 stars: 1836
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: fastapi-cache - name: vue-fastapi-admin
html_url: https://github.com/long2ice/fastapi-cache html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin
stars: 1677 stars: 1831
owner_login: long2ice owner_login: mizhexiaoxiao
owner_html_url: https://github.com/long2ice owner_html_url: https://github.com/mizhexiaoxiao
- name: python-week-2022
html_url: https://github.com/rochacbruno/python-week-2022
stars: 1817
owner_login: rochacbruno
owner_html_url: https://github.com/rochacbruno
- name: slowapi - name: slowapi
html_url: https://github.com/laurentS/slowapi html_url: https://github.com/laurentS/slowapi
stars: 1669 stars: 1798
owner_login: laurentS owner_login: laurentS
owner_html_url: https://github.com/laurentS owner_html_url: https://github.com/laurentS
- name: langchain-serve - name: fastapi-cache
html_url: https://github.com/jina-ai/langchain-serve html_url: https://github.com/long2ice/fastapi-cache
stars: 1632 stars: 1789
owner_login: jina-ai owner_login: long2ice
owner_html_url: https://github.com/jina-ai owner_html_url: https://github.com/long2ice
- name: ormar
html_url: https://github.com/collerek/ormar
stars: 1783
owner_login: collerek
owner_html_url: https://github.com/collerek
- name: termpair - name: termpair
html_url: https://github.com/cs01/termpair html_url: https://github.com/cs01/termpair
stars: 1621 stars: 1716
owner_login: cs01 owner_login: cs01
owner_html_url: https://github.com/cs01 owner_html_url: https://github.com/cs01
- name: FastAPI-boilerplate - name: FastAPI-boilerplate
html_url: https://github.com/benavlabs/FastAPI-boilerplate html_url: https://github.com/benavlabs/FastAPI-boilerplate
stars: 1596 stars: 1660
owner_login: benavlabs owner_login: benavlabs
owner_html_url: https://github.com/benavlabs owner_html_url: https://github.com/benavlabs
- name: coronavirus-tracker-api - name: fastapi-langgraph-agent-production-ready-template
html_url: https://github.com/ExpDev07/coronavirus-tracker-api html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template
stars: 1573 stars: 1638
owner_login: ExpDev07 owner_login: wassim249
owner_html_url: https://github.com/ExpDev07 owner_html_url: https://github.com/wassim249
- name: fastapi-crudrouter - name: langchain-serve
html_url: https://github.com/awtkns/fastapi-crudrouter html_url: https://github.com/jina-ai/langchain-serve
stars: 1553 stars: 1635
owner_login: awtkns owner_login: jina-ai
owner_html_url: https://github.com/awtkns owner_html_url: https://github.com/jina-ai
- 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: 1485 stars: 1589
owner_login: Kludex owner_login: Kludex
owner_html_url: https://github.com/Kludex owner_html_url: https://github.com/Kludex
- name: fastapi-pagination - name: fastapi-pagination
html_url: https://github.com/uriyyo/fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination
stars: 1473 stars: 1585
owner_login: uriyyo owner_login: uriyyo
owner_html_url: https://github.com/uriyyo owner_html_url: https://github.com/uriyyo
- name: coronavirus-tracker-api
html_url: https://github.com/ExpDev07/coronavirus-tracker-api
stars: 1574
owner_login: ExpDev07
owner_html_url: https://github.com/ExpDev07
- name: fastapi-crudrouter
html_url: https://github.com/awtkns/fastapi-crudrouter
stars: 1559
owner_login: awtkns
owner_html_url: https://github.com/awtkns
- name: bracket - name: bracket
html_url: https://github.com/evroon/bracket html_url: https://github.com/evroon/bracket
stars: 1470 stars: 1489
owner_login: evroon owner_login: evroon
owner_html_url: https://github.com/evroon owner_html_url: https://github.com/evroon
- name: fastapi-langgraph-agent-production-ready-template - name: fastapi-amis-admin
html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template html_url: https://github.com/amisadmin/fastapi-amis-admin
stars: 1456 stars: 1475
owner_login: wassim249 owner_login: amisadmin
owner_html_url: https://github.com/wassim249 owner_html_url: https://github.com/amisadmin
- name: fastapi-boilerplate - name: fastapi-boilerplate
html_url: https://github.com/teamhide/fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate
stars: 1424 stars: 1436
owner_login: teamhide owner_login: teamhide
owner_html_url: https://github.com/teamhide owner_html_url: https://github.com/teamhide
- 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: 1420 stars: 1426
owner_login: DjangoEx owner_login: DjangoEx
owner_html_url: https://github.com/DjangoEx owner_html_url: https://github.com/DjangoEx
- name: fastapi-amis-admin
html_url: https://github.com/amisadmin/fastapi-amis-admin
stars: 1363
owner_login: amisadmin
owner_html_url: https://github.com/amisadmin
- name: fastcrud - name: fastcrud
html_url: https://github.com/benavlabs/fastcrud html_url: https://github.com/benavlabs/fastcrud
stars: 1362 stars: 1414
owner_login: benavlabs owner_login: benavlabs
owner_html_url: https://github.com/benavlabs owner_html_url: https://github.com/benavlabs
- name: prometheus-fastapi-instrumentator
html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator
stars: 1388
owner_login: trallnag
owner_html_url: https://github.com/trallnag
- name: fastapi_best_architecture
html_url: https://github.com/fastapi-practices/fastapi_best_architecture
stars: 1378
owner_login: fastapi-practices
owner_html_url: https://github.com/fastapi-practices
- name: fastapi-code-generator
html_url: https://github.com/koxudaxi/fastapi-code-generator
stars: 1375
owner_login: koxudaxi
owner_html_url: https://github.com/koxudaxi
- name: budgetml - name: budgetml
html_url: https://github.com/ebhy/budgetml html_url: https://github.com/ebhy/budgetml
stars: 1345 stars: 1345
@ -370,126 +390,106 @@
owner_html_url: https://github.com/ebhy owner_html_url: https://github.com/ebhy
- name: fastapi-tutorial - name: fastapi-tutorial
html_url: https://github.com/liaogx/fastapi-tutorial html_url: https://github.com/liaogx/fastapi-tutorial
stars: 1315 stars: 1327
owner_login: liaogx owner_login: liaogx
owner_html_url: https://github.com/liaogx owner_html_url: https://github.com/liaogx
- name: fastapi_best_architecture - name: fastapi-alembic-sqlmodel-async
html_url: https://github.com/fastapi-practices/fastapi_best_architecture html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async
stars: 1311 stars: 1259
owner_login: fastapi-practices owner_login: jonra1993
owner_html_url: https://github.com/fastapi-practices owner_html_url: https://github.com/jonra1993
- name: fastapi-code-generator - name: fastapi-scaff
html_url: https://github.com/koxudaxi/fastapi-code-generator html_url: https://github.com/atpuxiner/fastapi-scaff
stars: 1270 stars: 1255
owner_login: koxudaxi owner_login: atpuxiner
owner_html_url: https://github.com/koxudaxi owner_html_url: https://github.com/atpuxiner
- name: prometheus-fastapi-instrumentator
html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator
stars: 1264
owner_login: trallnag
owner_html_url: https://github.com/trallnag
- 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: 1243 stars: 1254
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: bolt-python - name: bolt-python
html_url: https://github.com/slackapi/bolt-python html_url: https://github.com/slackapi/bolt-python
stars: 1238 stars: 1253
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: fastapi_production_template
html_url: https://github.com/zhanymkanov/fastapi_production_template html_url: https://github.com/zhanymkanov/fastapi_production_template
stars: 1209 stars: 1217
owner_login: zhanymkanov owner_login: zhanymkanov
owner_html_url: https://github.com/zhanymkanov owner_html_url: https://github.com/zhanymkanov
- name: fastapi-scaff
html_url: https://github.com/atpuxiner/fastapi-scaff
stars: 1200
owner_login: atpuxiner
owner_html_url: https://github.com/atpuxiner
- 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: 1173 stars: 1176
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-alembic-sqlmodel-async
html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async
stars: 1162
owner_login: jonra1993
owner_html_url: https://github.com/jonra1993
- name: odmantic
html_url: https://github.com/art049/odmantic
stars: 1137
owner_login: art049
owner_html_url: https://github.com/art049
- name: restish - name: restish
html_url: https://github.com/rest-sh/restish html_url: https://github.com/rest-sh/restish
stars: 1129 stars: 1140
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: kubetorch - name: odmantic
html_url: https://github.com/run-house/kubetorch html_url: https://github.com/art049/odmantic
stars: 1065 stars: 1138
owner_login: run-house owner_login: art049
owner_html_url: https://github.com/run-house owner_html_url: https://github.com/art049
- name: flock
html_url: https://github.com/Onelevenvy/flock
stars: 1039
owner_login: Onelevenvy
owner_html_url: https://github.com/Onelevenvy
- name: authx - name: authx
html_url: https://github.com/yezz123/authx html_url: https://github.com/yezz123/authx
stars: 1017 stars: 1119
owner_login: yezz123 owner_login: yezz123
owner_html_url: https://github.com/yezz123 owner_html_url: https://github.com/yezz123
- name: autollm - name: NoteDiscovery
html_url: https://github.com/viddexa/autollm html_url: https://github.com/gamosoft/NoteDiscovery
stars: 997 stars: 1107
owner_login: viddexa owner_login: gamosoft
owner_html_url: https://github.com/viddexa owner_html_url: https://github.com/gamosoft
- name: lanarky - name: flock
html_url: https://github.com/ajndkr/lanarky html_url: https://github.com/Onelevenvy/flock
stars: 993 stars: 1055
owner_login: ajndkr owner_login: Onelevenvy
owner_html_url: https://github.com/ajndkr owner_html_url: https://github.com/Onelevenvy
- name: RuoYi-Vue3-FastAPI - name: fastapi-observability
html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI html_url: https://github.com/blueswen/fastapi-observability
stars: 974 stars: 1038
owner_login: insistence owner_login: blueswen
owner_html_url: https://github.com/insistence owner_html_url: https://github.com/blueswen
- name: aktools - name: aktools
html_url: https://github.com/akfamily/aktools html_url: https://github.com/akfamily/aktools
stars: 972 stars: 1027
owner_login: akfamily owner_login: akfamily
owner_html_url: https://github.com/akfamily owner_html_url: https://github.com/akfamily
- name: RuoYi-Vue3-FastAPI
html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI
stars: 1016
owner_login: insistence
owner_html_url: https://github.com/insistence
- name: autollm
html_url: https://github.com/viddexa/autollm
stars: 1002
owner_login: viddexa
owner_html_url: https://github.com/viddexa
- name: titiler - name: titiler
html_url: https://github.com/developmentseed/titiler html_url: https://github.com/developmentseed/titiler
stars: 965 stars: 999
owner_login: developmentseed owner_login: developmentseed
owner_html_url: https://github.com/developmentseed owner_html_url: https://github.com/developmentseed
- name: secure - name: lanarky
html_url: https://github.com/TypeError/secure html_url: https://github.com/ajndkr/lanarky
stars: 953 stars: 994
owner_login: TypeError owner_login: ajndkr
owner_html_url: https://github.com/TypeError owner_html_url: https://github.com/ajndkr
- name: energy-forecasting
html_url: https://github.com/iusztinpaul/energy-forecasting
stars: 949
owner_login: iusztinpaul
owner_html_url: https://github.com/iusztinpaul
- name: every-pdf - name: every-pdf
html_url: https://github.com/DDULDDUCK/every-pdf html_url: https://github.com/DDULDDUCK/every-pdf
stars: 942 stars: 985
owner_login: DDULDDUCK owner_login: DDULDDUCK
owner_html_url: https://github.com/DDULDDUCK owner_html_url: https://github.com/DDULDDUCK
- name: langcorn - name: enterprise-deep-research
html_url: https://github.com/msoedov/langcorn html_url: https://github.com/SalesforceAIResearch/enterprise-deep-research
stars: 933 stars: 973
owner_login: msoedov owner_login: SalesforceAIResearch
owner_html_url: https://github.com/msoedov owner_html_url: https://github.com/SalesforceAIResearch
- name: fastapi-observability - name: fastapi-mail
html_url: https://github.com/blueswen/fastapi-observability html_url: https://github.com/sabuhish/fastapi-mail
stars: 923 stars: 964
owner_login: blueswen owner_login: sabuhish
owner_html_url: https://github.com/blueswen owner_html_url: https://github.com/sabuhish

8
docs/en/docs/advanced/behind-a-proxy.md

@ -443,6 +443,14 @@ The docs UI will interact with the server that you select.
/// ///
/// note | Technical Details
The `servers` property in the OpenAPI specification is optional.
If you don't specify the `servers` parameter and `root_path` is equal to `/`, the `servers` property in the generated OpenAPI schema will be omitted entirely by default, which is the equivalent of a single server with a `url` value of `/`.
///
### Disable automatic server from `root_path` { #disable-automatic-server-from-root-path } ### Disable automatic server from `root_path` { #disable-automatic-server-from-root-path }
If you don't want **FastAPI** to include an automatic server using the `root_path`, you can use the parameter `root_path_in_servers=False`: If you don't want **FastAPI** to include an automatic server using the `root_path`, you can use the parameter `root_path_in_servers=False`:

BIN
docs/en/docs/img/sponsors/greptile-banner.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
docs/en/docs/img/sponsors/greptile.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

2
docs/en/docs/index.md

@ -46,7 +46,7 @@ The key features are:
* **Robust**: Get production-ready code. With automatic interactive documentation. * **Robust**: Get production-ready code. With automatic interactive documentation.
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>. * **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>* estimation based on tests on an internal development team, building production applications.</small> <small>* estimation based on tests conducted by an internal development team, building production applications.</small>
## Sponsors { #sponsors } ## Sponsors { #sponsors }

42
docs/en/docs/release-notes.md

@ -7,8 +7,50 @@ hide:
## Latest Changes ## Latest Changes
## 0.123.4
### Fixes
* 🐛 Fix OpenAPI schema support for computed fields when using `separate_input_output_schemas=False`. PR [#13207](https://github.com/fastapi/fastapi/pull/13207) by [@vgrafe](https://github.com/vgrafe).
### Docs
* 📝 Fix docstring of `servers` parameter. PR [#14405](https://github.com/fastapi/fastapi/pull/14405) by [@YuriiMotov](https://github.com/YuriiMotov).
## 0.123.3
### Fixes
* 🐛 Fix Query\Header\Cookie parameter model alias. PR [#14360](https://github.com/fastapi/fastapi/pull/14360) by [@YuriiMotov](https://github.com/YuriiMotov).
* 🐛 Fix optional sequence handling in `serialize sequence value` with Pydantic V2. PR [#14297](https://github.com/fastapi/fastapi/pull/14297) by [@YuriiMotov](https://github.com/YuriiMotov).
## 0.123.2
### Fixes
* 🐛 Fix unformatted `{type_}` in FastAPIError. PR [#14416](https://github.com/fastapi/fastapi/pull/14416) by [@Just-Helpful](https://github.com/Just-Helpful).
* 🐛 Fix parsing extra non-body parameter list. PR [#14356](https://github.com/fastapi/fastapi/pull/14356) by [@YuriiMotov](https://github.com/YuriiMotov).
* 🐛 Fix parsing extra `Form` parameter list. PR [#14303](https://github.com/fastapi/fastapi/pull/14303) by [@YuriiMotov](https://github.com/YuriiMotov).
* 🐛 Fix support for form values with empty strings interpreted as missing (`None` if that's the default), for compatibility with HTML forms. PR [#13537](https://github.com/fastapi/fastapi/pull/13537) by [@MarinPostma](https://github.com/MarinPostma).
### Docs
* 📝 Add tip on how to install `pip` in case of `No module named pip` error in `virtual-environments.md`. PR [#14211](https://github.com/fastapi/fastapi/pull/14211) by [@zadevhub](https://github.com/zadevhub).
* 📝 Update Primary Key notes for the SQL databases tutorial to avoid confusion. PR [#14120](https://github.com/fastapi/fastapi/pull/14120) by [@FlaviusRaducu](https://github.com/FlaviusRaducu).
* 📝 Clarify estimation note in documentation. PR [#14070](https://github.com/fastapi/fastapi/pull/14070) by [@SaisakthiM](https://github.com/SaisakthiM).
## 0.123.1
### Fixes
* 🐛 Avoid accessing non-existing "$ref" key for Pydantic v2 compat remapping. PR [#14361](https://github.com/fastapi/fastapi/pull/14361) by [@svlandeg](https://github.com/svlandeg).
* 🐛 Fix `TypeError` when encoding a decimal with a `NaN` or `Infinity` value. PR [#12935](https://github.com/fastapi/fastapi/pull/12935) by [@kentwelcome](https://github.com/kentwelcome).
### Internal ### Internal
* 🐛 Fix Windows UnicodeEncodeError in CLI test. PR [#14295](https://github.com/fastapi/fastapi/pull/14295) by [@hemanth-thirthahalli](https://github.com/hemanth-thirthahalli).
* 🔧 Update sponsors: add Greptile. PR [#14429](https://github.com/fastapi/fastapi/pull/14429) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI GitHub topic repositories. PR [#14426](https://github.com/fastapi/fastapi/pull/14426) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Bump markdown-include-variants from 0.0.6 to 0.0.7. PR [#14423](https://github.com/fastapi/fastapi/pull/14423) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ Bump markdown-include-variants from 0.0.6 to 0.0.7. PR [#14423](https://github.com/fastapi/fastapi/pull/14423) by [@YuriiMotov](https://github.com/YuriiMotov).
* 👥 Update FastAPI People - Sponsors. PR [#14422](https://github.com/fastapi/fastapi/pull/14422) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Sponsors. PR [#14422](https://github.com/fastapi/fastapi/pull/14422) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI People - Contributors and Translators. PR [#14420](https://github.com/fastapi/fastapi/pull/14420) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#14420](https://github.com/fastapi/fastapi/pull/14420) by [@tiangolo](https://github.com/tiangolo).

2
docs/en/docs/tutorial/sql-databases.md

@ -65,7 +65,7 @@ There are a few differences:
* `Field(primary_key=True)` tells SQLModel that the `id` is the **primary key** in the SQL database (you can learn more about SQL primary keys in the SQLModel docs). * `Field(primary_key=True)` tells SQLModel that the `id` is the **primary key** in the SQL database (you can learn more about SQL primary keys in the SQLModel docs).
By having the type as `int | None`, SQLModel will know that this column should be an `INTEGER` in the SQL database and that it should be `NULLABLE`. **Note:** We use `int | None` for the primary key field so that in Python code we can *create an object without an `id`* (`id=None`), assuming the database will *generate it when saving*. SQLModel understands that the database will provide the `id` and *defines the column as a non-null `INTEGER`* in the database schema. See <a href="https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id" class="external-link" target="_blank">SQLModel docs on primary keys</a> for details.
* `Field(index=True)` tells SQLModel that it should create a **SQL index** for this column, that would allow faster lookups in the database when reading data filtered by this column. * `Field(index=True)` tells SQLModel that it should create a **SQL index** for this column, that would allow faster lookups in the database when reading data filtered by this column.

20
docs/en/docs/virtual-environments.md

@ -242,6 +242,26 @@ $ python -m pip install --upgrade pip
</div> </div>
/// tip
Sometimes, you might get a **`No module named pip`** error when trying to upgrade pip.
If this happens, install and upgrade pip using the command below:
<div class="termy">
```console
$ python -m ensurepip --upgrade
---> 100%
```
</div>
This command will install pip if it is not already installed and also ensures that the installed version of pip is at least as recent as the one available in `ensurepip`.
///
## Add `.gitignore` { #add-gitignore } ## Add `.gitignore` { #add-gitignore }
If you are using **Git** (you should), add a `.gitignore` file to exclude everything in your `.venv` from Git. If you are using **Git** (you should), add a `.gitignore` file to exclude everything in your `.venv` from Git.

6
docs/en/overrides/main.html

@ -93,6 +93,12 @@
<img class="sponsor-image" src="/img/sponsors/serpapi-banner.png" /> <img class="sponsor-image" src="/img/sponsors/serpapi-banner.png" />
</a> </a>
</div> </div>
<div class="item">
<a title="Greptile: The AI Code Reviewer" style="display: block; position: relative;" href="https://www.greptile.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=fastapi_sponsor_page" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/greptile-banner.png" />
</a>
</div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

2
fastapi/__init__.py

@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production""" """FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
__version__ = "0.123.0" __version__ = "0.123.4"
from starlette import status as status from starlette import status as status

23
fastapi/_compat/v2.py

@ -180,8 +180,13 @@ def get_schema_from_model_field(
], ],
separate_input_output_schemas: bool = True, separate_input_output_schemas: bool = True,
) -> Dict[str, Any]: ) -> Dict[str, Any]:
computed_fields = field._type_adapter.core_schema.get("schema", {}).get(
"computed_fields", []
)
override_mode: Union[Literal["validation"], None] = ( override_mode: Union[Literal["validation"], None] = (
None if separate_input_output_schemas else "validation" None
if (separate_input_output_schemas or len(computed_fields) > 0)
else "validation"
) )
# This expects that GenerateJsonSchema was already used to generate the definitions # This expects that GenerateJsonSchema was already used to generate the definitions
json_schema = field_mapping[(field, override_mode or field.mode)] json_schema = field_mapping[(field, override_mode or field.mode)]
@ -203,9 +208,14 @@ def get_definitions(
Dict[Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], Dict[Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
Dict[str, Dict[str, Any]], Dict[str, Dict[str, Any]],
]: ]:
has_computed_fields: bool = any(
field._type_adapter.core_schema.get("schema", {}).get("computed_fields", [])
for field in fields
)
schema_generator = GenerateJsonSchema(ref_template=REF_TEMPLATE) schema_generator = GenerateJsonSchema(ref_template=REF_TEMPLATE)
override_mode: Union[Literal["validation"], None] = ( override_mode: Union[Literal["validation"], None] = (
None if separate_input_output_schemas else "validation" None if (separate_input_output_schemas or has_computed_fields) else "validation"
) )
validation_fields = [field for field in fields if field.mode == "validation"] validation_fields = [field for field in fields if field.mode == "validation"]
serialization_fields = [field for field in fields if field.mode == "serialization"] serialization_fields = [field for field in fields if field.mode == "serialization"]
@ -304,7 +314,7 @@ def _remap_definitions_and_field_mappings(
old_name_to_new_name_map = {} old_name_to_new_name_map = {}
for field_key, schema in field_mapping.items(): for field_key, schema in field_mapping.items():
model = field_key[0].type_ model = field_key[0].type_
if model not in model_name_map: if model not in model_name_map or "$ref" not in schema:
continue continue
new_name = model_name_map[model] new_name = model_name_map[model]
old_name = schema["$ref"].split("/")[-1] old_name = schema["$ref"].split("/")[-1]
@ -371,6 +381,13 @@ def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo:
def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]: def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]:
origin_type = get_origin(field.field_info.annotation) or field.field_info.annotation origin_type = get_origin(field.field_info.annotation) or field.field_info.annotation
if origin_type is Union: # Handle optional sequences
union_args = get_args(field.field_info.annotation)
for union_arg in union_args:
if union_arg is type(None):
continue
origin_type = get_origin(union_arg) or union_arg
break
assert issubclass(origin_type, shared.sequence_types) # type: ignore[arg-type] assert issubclass(origin_type, shared.sequence_types) # type: ignore[arg-type]
return shared.sequence_annotation_to_type[origin_type](value) # type: ignore[no-any-return] return shared.sequence_annotation_to_type[origin_type](value) # type: ignore[no-any-return]

7
fastapi/applications.py

@ -301,7 +301,12 @@ class FastAPI(Starlette):
browser tabs open). Or if you want to leave fixed the possible URLs. browser tabs open). Or if you want to leave fixed the possible URLs.
If the servers `list` is not provided, or is an empty `list`, the If the servers `list` is not provided, or is an empty `list`, the
default value would be a `dict` with a `url` value of `/`. `servers` property in the generated OpenAPI will be:
* a `dict` with a `url` value of the application's mounting point
(`root_path`) if it's different from `/`.
* otherwise, the `servers` property will be omitted from the OpenAPI
schema.
Each item in the `list` is a `dict` containing: Each item in the `list` is a `dict` containing:

25
fastapi/dependencies/utils.py

@ -787,13 +787,19 @@ def request_params_to_args(
) )
value = _get_multidict_value(field, received_params, alias=alias) value = _get_multidict_value(field, received_params, alias=alias)
if value is not None: if value is not None:
params_to_process[field.name] = value params_to_process[field.alias] = value
processed_keys.add(alias or field.alias) processed_keys.add(alias or field.alias)
processed_keys.add(field.name)
for key, value in received_params.items(): for key in received_params.keys():
if key not in processed_keys: if key not in processed_keys:
params_to_process[key] = value if hasattr(received_params, "getlist"):
value = received_params.getlist(key)
if isinstance(value, list) and (len(value) == 1):
params_to_process[key] = value[0]
else:
params_to_process[key] = value
else:
params_to_process[key] = received_params.get(key)
if single_not_embedded_field: if single_not_embedded_field:
field_info = first_field.field_info field_info = first_field.field_info
@ -902,9 +908,14 @@ async def _extract_form_body(
value = serialize_sequence_value(field=field, value=results) value = serialize_sequence_value(field=field, value=results)
if value is not None: if value is not None:
values[field.alias] = value values[field.alias] = value
for key, value in received_body.items(): field_aliases = {field.alias for field in body_fields}
if key not in values: for key in received_body.keys():
values[key] = value if key not in field_aliases:
param_values = received_body.getlist(key)
if len(param_values) == 1:
values[key] = param_values[0]
else:
values[key] = param_values
return values return values

12
fastapi/encoders.py

@ -34,14 +34,14 @@ def isoformat(o: Union[datetime.date, datetime.time]) -> str:
return o.isoformat() return o.isoformat()
# Taken from Pydantic v1 as is # Adapted from Pydantic v1
# TODO: pv2 should this return strings instead? # TODO: pv2 should this return strings instead?
def decimal_encoder(dec_value: Decimal) -> Union[int, float]: def decimal_encoder(dec_value: Decimal) -> Union[int, float]:
""" """
Encodes a Decimal as int of there's no exponent, otherwise float Encodes a Decimal as int if there's no exponent, otherwise float
This is useful when we use ConstrainedDecimal to represent Numeric(x,0) This is useful when we use ConstrainedDecimal to represent Numeric(x,0)
where a integer (but not int typed) is used. Encoding this as a float where an integer (but not int typed) is used. Encoding this as a float
results in failed round-tripping between encode and parse. results in failed round-tripping between encode and parse.
Our Id type is a prime example of this. Our Id type is a prime example of this.
@ -50,8 +50,12 @@ def decimal_encoder(dec_value: Decimal) -> Union[int, float]:
>>> decimal_encoder(Decimal("1")) >>> decimal_encoder(Decimal("1"))
1 1
>>> decimal_encoder(Decimal("NaN"))
nan
""" """
if dec_value.as_tuple().exponent >= 0: # type: ignore[operator] exponent = dec_value.as_tuple().exponent
if isinstance(exponent, int) and exponent >= 0:
return int(dec_value) return int(dec_value)
else: else:
return float(dec_value) return float(dec_value)

12
fastapi/utils.py

@ -110,7 +110,9 @@ def create_model_field(
try: try:
return v1.ModelField(**v1_kwargs) # type: ignore[no-any-return] return v1.ModelField(**v1_kwargs) # type: ignore[no-any-return]
except RuntimeError: except RuntimeError:
raise fastapi.exceptions.FastAPIError(_invalid_args_message) from None raise fastapi.exceptions.FastAPIError(
_invalid_args_message.format(type_=type_)
) from None
elif PYDANTIC_V2: elif PYDANTIC_V2:
from ._compat import v2 from ._compat import v2
@ -121,7 +123,9 @@ def create_model_field(
try: try:
return v2.ModelField(**kwargs) # type: ignore[return-value,arg-type] return v2.ModelField(**kwargs) # type: ignore[return-value,arg-type]
except PydanticSchemaGenerationError: except PydanticSchemaGenerationError:
raise fastapi.exceptions.FastAPIError(_invalid_args_message) from None raise fastapi.exceptions.FastAPIError(
_invalid_args_message.format(type_=type_)
) from None
# Pydantic v2 is not installed, but it's not a Pydantic v1 ModelField, it could be # Pydantic v2 is not installed, but it's not a Pydantic v1 ModelField, it could be
# a Pydantic v1 type, like a constrained int # a Pydantic v1 type, like a constrained int
from fastapi._compat import v1 from fastapi._compat import v1
@ -129,7 +133,9 @@ def create_model_field(
try: try:
return v1.ModelField(**v1_kwargs) # type: ignore[no-any-return] return v1.ModelField(**v1_kwargs) # type: ignore[no-any-return]
except RuntimeError: except RuntimeError:
raise fastapi.exceptions.FastAPIError(_invalid_args_message) from None raise fastapi.exceptions.FastAPIError(
_invalid_args_message.format(type_=type_)
) from None
def create_cloned_field( def create_cloned_field(

24
tests/test_compat.py

@ -136,6 +136,30 @@ def test_is_uploadfile_sequence_annotation():
assert is_uploadfile_sequence_annotation(Union[List[str], List[UploadFile]]) assert is_uploadfile_sequence_annotation(Union[List[str], List[UploadFile]])
@needs_pydanticv2
def test_serialize_sequence_value_with_optional_list():
"""Test that serialize_sequence_value handles optional lists correctly."""
from fastapi._compat import v2
field_info = FieldInfo(annotation=Union[List[str], None])
field = v2.ModelField(name="items", field_info=field_info)
result = v2.serialize_sequence_value(field=field, value=["a", "b", "c"])
assert result == ["a", "b", "c"]
assert isinstance(result, list)
@needs_pydanticv2
def test_serialize_sequence_value_with_none_first_in_union():
"""Test that serialize_sequence_value handles Union[None, List[...]] correctly."""
from fastapi._compat import v2
field_info = FieldInfo(annotation=Union[None, List[str]])
field = v2.ModelField(name="items", field_info=field_info)
result = v2.serialize_sequence_value(field=field, value=["x", "y"])
assert result == ["x", "y"]
assert isinstance(result, list)
@needs_py_lt_314 @needs_py_lt_314
def test_is_pv1_scalar_field(): def test_is_pv1_scalar_field():
from fastapi._compat import v1 from fastapi._compat import v1

7
tests/test_computed_fields.py

@ -6,8 +6,9 @@ from .utils import needs_pydanticv2
@pytest.fixture(name="client") @pytest.fixture(name="client")
def get_client(): def get_client(request):
app = FastAPI() separate_input_output_schemas = request.param
app = FastAPI(separate_input_output_schemas=separate_input_output_schemas)
from pydantic import BaseModel, computed_field from pydantic import BaseModel, computed_field
@ -32,6 +33,7 @@ def get_client():
return client return client
@pytest.mark.parametrize("client", [True, False], indirect=True)
@pytest.mark.parametrize("path", ["/", "/responses"]) @pytest.mark.parametrize("path", ["/", "/responses"])
@needs_pydanticv2 @needs_pydanticv2
def test_get(client: TestClient, path: str): def test_get(client: TestClient, path: str):
@ -40,6 +42,7 @@ def test_get(client: TestClient, path: str):
assert response.json() == {"width": 3, "length": 4, "area": 12} assert response.json() == {"width": 3, "length": 4, "area": 12}
@pytest.mark.parametrize("client", [True, False], indirect=True)
@needs_pydanticv2 @needs_pydanticv2
def test_openapi_schema(client: TestClient): def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json") response = client.get("/openapi.json")

2
tests/test_fastapi_cli.py

@ -1,3 +1,4 @@
import os
import subprocess import subprocess
import sys import sys
from unittest.mock import patch from unittest.mock import patch
@ -20,6 +21,7 @@ def test_fastapi_cli():
], ],
capture_output=True, capture_output=True,
encoding="utf-8", encoding="utf-8",
env={**os.environ, "PYTHONIOENCODING": "utf-8"},
) )
assert result.returncode == 1, result.stdout assert result.returncode == 1, result.stdout
assert "Path does not exist non_existent_file.py" in result.stdout assert "Path does not exist non_existent_file.py" in result.stdout

35
tests/test_form_default.py

@ -0,0 +1,35 @@
from typing import Optional
from fastapi import FastAPI, File, Form
from starlette.testclient import TestClient
from typing_extensions import Annotated
app = FastAPI()
@app.post("/urlencoded")
async def post_url_encoded(age: Annotated[Optional[int], Form()] = None):
return age
@app.post("/multipart")
async def post_multi_part(
age: Annotated[Optional[int], Form()] = None,
file: Annotated[Optional[bytes], File()] = None,
):
return {"file": file, "age": age}
client = TestClient(app)
def test_form_default_url_encoded():
response = client.post("/urlencoded", data={"age": ""})
assert response.status_code == 200
assert response.text == "null"
def test_form_default_multi_part():
response = client.post("/multipart", data={"age": ""})
assert response.status_code == 200
assert response.json() == {"file": None, "age": None}

47
tests/test_forms_single_model.py

@ -2,6 +2,7 @@ from typing import List, Optional
from dirty_equals import IsDict from dirty_equals import IsDict
from fastapi import FastAPI, Form from fastapi import FastAPI, Form
from fastapi._compat import PYDANTIC_V2
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from typing_extensions import Annotated from typing_extensions import Annotated
@ -17,11 +18,27 @@ class FormModel(BaseModel):
alias_with: str = Field(alias="with", default="nothing") alias_with: str = Field(alias="with", default="nothing")
class FormModelExtraAllow(BaseModel):
param: str
if PYDANTIC_V2:
model_config = {"extra": "allow"}
else:
class Config:
extra = "allow"
@app.post("/form/") @app.post("/form/")
def post_form(user: Annotated[FormModel, Form()]): def post_form(user: Annotated[FormModel, Form()]):
return user return user
@app.post("/form-extra-allow/")
def post_form_extra_allow(params: Annotated[FormModelExtraAllow, Form()]):
return params
client = TestClient(app) client = TestClient(app)
@ -131,3 +148,33 @@ def test_no_data():
] ]
} }
) )
def test_extra_param_single():
response = client.post(
"/form-extra-allow/",
data={
"param": "123",
"extra_param": "456",
},
)
assert response.status_code == 200, response.text
assert response.json() == {
"param": "123",
"extra_param": "456",
}
def test_extra_param_list():
response = client.post(
"/form-extra-allow/",
data={
"param": "123",
"extra_params": ["456", "789"],
},
)
assert response.status_code == 200, response.text
assert response.json() == {
"param": "123",
"extra_params": ["456", "789"],
}

15
tests/test_jsonable_encoder.py

@ -3,6 +3,7 @@ from dataclasses import dataclass
from datetime import datetime, timezone from datetime import datetime, timezone
from decimal import Decimal from decimal import Decimal
from enum import Enum from enum import Enum
from math import isinf, isnan
from pathlib import PurePath, PurePosixPath, PureWindowsPath from pathlib import PurePath, PurePosixPath, PureWindowsPath
from typing import Optional from typing import Optional
@ -306,6 +307,20 @@ def test_decimal_encoder_int():
assert jsonable_encoder(data) == {"value": 2} assert jsonable_encoder(data) == {"value": 2}
@needs_pydanticv2
def test_decimal_encoder_nan():
data = {"value": Decimal("NaN")}
assert isnan(jsonable_encoder(data)["value"])
@needs_pydanticv2
def test_decimal_encoder_infinity():
data = {"value": Decimal("Infinity")}
assert isinf(jsonable_encoder(data)["value"])
data = {"value": Decimal("-Infinity")}
assert isinf(jsonable_encoder(data)["value"])
def test_encode_deque_encodes_child_models(): def test_encode_deque_encodes_child_models():
class Model(BaseModel): class Model(BaseModel):
test: str test: str

30
tests/test_optional_file_list.py

@ -0,0 +1,30 @@
from typing import List, Optional
from fastapi import FastAPI, File
from fastapi.testclient import TestClient
app = FastAPI()
@app.post("/files")
async def upload_files(files: Optional[List[bytes]] = File(None)):
if files is None:
return {"files_count": 0}
return {"files_count": len(files), "sizes": [len(f) for f in files]}
def test_optional_bytes_list():
client = TestClient(app)
response = client.post(
"/files",
files=[("files", b"content1"), ("files", b"content2")],
)
assert response.status_code == 200
assert response.json() == {"files_count": 2, "sizes": [8, 8]}
def test_optional_bytes_list_no_files():
client = TestClient(app)
response = client.post("/files")
assert response.status_code == 200
assert response.json() == {"files_count": 0}

111
tests/test_query_cookie_header_model_extra_params.py

@ -0,0 +1,111 @@
from fastapi import Cookie, FastAPI, Header, Query
from fastapi._compat import PYDANTIC_V2
from fastapi.testclient import TestClient
from pydantic import BaseModel
app = FastAPI()
class Model(BaseModel):
param: str
if PYDANTIC_V2:
model_config = {"extra": "allow"}
else:
class Config:
extra = "allow"
@app.get("/query")
async def query_model_with_extra(data: Model = Query()):
return data
@app.get("/header")
async def header_model_with_extra(data: Model = Header()):
return data
@app.get("/cookie")
async def cookies_model_with_extra(data: Model = Cookie()):
return data
def test_query_pass_extra_list():
client = TestClient(app)
resp = client.get(
"/query",
params={
"param": "123",
"param2": ["456", "789"], # Pass a list of values as extra parameter
},
)
assert resp.status_code == 200
assert resp.json() == {
"param": "123",
"param2": ["456", "789"],
}
def test_query_pass_extra_single():
client = TestClient(app)
resp = client.get(
"/query",
params={
"param": "123",
"param2": "456",
},
)
assert resp.status_code == 200
assert resp.json() == {
"param": "123",
"param2": "456",
}
def test_header_pass_extra_list():
client = TestClient(app)
resp = client.get(
"/header",
headers=[
("param", "123"),
("param2", "456"), # Pass a list of values as extra parameter
("param2", "789"),
],
)
assert resp.status_code == 200
resp_json = resp.json()
assert "param2" in resp_json
assert resp_json["param2"] == ["456", "789"]
def test_header_pass_extra_single():
client = TestClient(app)
resp = client.get(
"/header",
headers=[
("param", "123"),
("param2", "456"),
],
)
assert resp.status_code == 200
resp_json = resp.json()
assert "param2" in resp_json
assert resp_json["param2"] == "456"
def test_cookie_pass_extra_list():
client = TestClient(app)
client.cookies = [
("param", "123"),
("param2", "456"), # Pass a list of values as extra parameter
("param2", "789"),
]
resp = client.get("/cookie")
assert resp.status_code == 200
resp_json = resp.json()
assert "param2" in resp_json
assert resp_json["param2"] == "789" # Cookies only keep the last value

76
tests/test_request_param_model_by_alias.py

@ -0,0 +1,76 @@
from dirty_equals import IsPartialDict
from fastapi import Cookie, FastAPI, Header, Query
from fastapi._compat import PYDANTIC_V2
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
app = FastAPI()
class Model(BaseModel):
param: str = Field(alias="param_alias")
@app.get("/query")
async def query_model(data: Model = Query()):
return {"param": data.param}
@app.get("/header")
async def header_model(data: Model = Header()):
return {"param": data.param}
@app.get("/cookie")
async def cookie_model(data: Model = Cookie()):
return {"param": data.param}
def test_query_model_with_alias():
client = TestClient(app)
response = client.get("/query", params={"param_alias": "value"})
assert response.status_code == 200, response.text
assert response.json() == {"param": "value"}
def test_header_model_with_alias():
client = TestClient(app)
response = client.get("/header", headers={"param_alias": "value"})
assert response.status_code == 200, response.text
assert response.json() == {"param": "value"}
def test_cookie_model_with_alias():
client = TestClient(app)
client.cookies.set("param_alias", "value")
response = client.get("/cookie")
assert response.status_code == 200, response.text
assert response.json() == {"param": "value"}
def test_query_model_with_alias_by_name():
client = TestClient(app)
response = client.get("/query", params={"param": "value"})
assert response.status_code == 422, response.text
details = response.json()
if PYDANTIC_V2:
assert details["detail"][0]["input"] == {"param": "value"}
def test_header_model_with_alias_by_name():
client = TestClient(app)
response = client.get("/header", headers={"param": "value"})
assert response.status_code == 422, response.text
details = response.json()
if PYDANTIC_V2:
assert details["detail"][0]["input"] == IsPartialDict({"param": "value"})
def test_cookie_model_with_alias_by_name():
client = TestClient(app)
client.cookies.set("param", "value")
response = client.get("/cookie")
assert response.status_code == 422, response.text
details = response.json()
if PYDANTIC_V2:
assert details["detail"][0]["input"] == {"param": "value"}

92
tests/test_schema_compat_pydantic_v2.py

@ -0,0 +1,92 @@
import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from pydantic import BaseModel
from tests.utils import needs_py310, needs_pydanticv2
@pytest.fixture(name="client")
def get_client():
from enum import Enum
app = FastAPI()
class PlatformRole(str, Enum):
admin = "admin"
user = "user"
class OtherRole(str, Enum): ...
class User(BaseModel):
username: str
role: PlatformRole | OtherRole
@app.get("/users")
async def get_user() -> User:
return {"username": "alice", "role": "admin"}
client = TestClient(app)
return client
@needs_py310
@needs_pydanticv2
def test_get(client: TestClient):
response = client.get("/users")
assert response.json() == {"username": "alice", "role": "admin"}
@needs_py310
@needs_pydanticv2
def test_openapi_schema(client: TestClient):
response = client.get("openapi.json")
assert response.json() == snapshot(
{
"openapi": "3.1.0",
"info": {"title": "FastAPI", "version": "0.1.0"},
"paths": {
"/users": {
"get": {
"summary": "Get User",
"operationId": "get_user_users_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/User"}
}
},
}
},
}
}
},
"components": {
"schemas": {
"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",
},
}
},
}
)

2
tests/test_tutorial/test_header_param_models/test_tutorial003.py

@ -77,7 +77,7 @@ def test_header_param_model_no_underscore(client: TestClient):
"user-agent": "testclient", "user-agent": "testclient",
"save-data": "true", "save-data": "true",
"if-modified-since": "yesterday", "if-modified-since": "yesterday",
"x-tag": "two", "x-tag": ["one", "two"],
}, },
} }
) )

Loading…
Cancel
Save