Compare commits

..

5 Commits

Author SHA1 Message Date
github-actions[bot]
dfadf80f48 🎨 Auto format 2026-01-22 11:22:53 +00:00
Yurii Motov
0e65c3167f Fix coverage 2026-01-22 12:22:20 +01:00
Yurii Motov
ef76935b10 Remove WSGIMiddleware from API reference 2026-01-22 12:18:57 +01:00
Yurii Motov
f55d2ee641 Add a2wsgi to test dependencies 2026-01-22 12:14:35 +01:00
Yurii Motov
c8f4a1b0d4 Update code example and docs page 2026-01-22 11:52:12 +01:00
14 changed files with 85 additions and 54 deletions

View File

@@ -164,6 +164,8 @@ $ pip install "fastapi[standard]"
Create a file `main.py` with: Create a file `main.py` with:
```Python ```Python
from typing import Union
from fastapi import FastAPI from fastapi import FastAPI
app = FastAPI() app = FastAPI()
@@ -175,7 +177,7 @@ def read_root():
@app.get("/items/{item_id}") @app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None): def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q} return {"item_id": item_id, "q": q}
``` ```
@@ -184,7 +186,9 @@ def read_item(item_id: int, q: str | None = None):
If your code uses `async` / `await`, use `async def`: If your code uses `async` / `await`, use `async def`:
```Python hl_lines="7 12" ```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI from fastapi import FastAPI
app = FastAPI() app = FastAPI()
@@ -196,7 +200,7 @@ async def read_root():
@app.get("/items/{item_id}") @app.get("/items/{item_id}")
async def read_item(item_id: int, q: str | None = None): async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q} return {"item_id": item_id, "q": q}
``` ```
@@ -287,7 +291,9 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
Declare the body using standard Python types, thanks to Pydantic. Declare the body using standard Python types, thanks to Pydantic.
```Python hl_lines="2 7-10 23-25" ```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI from fastapi import FastAPI
from pydantic import BaseModel from pydantic import BaseModel
@@ -297,7 +303,7 @@ app = FastAPI()
class Item(BaseModel): class Item(BaseModel):
name: str name: str
price: float price: float
is_offer: bool | None = None is_offer: Union[bool, None] = None
@app.get("/") @app.get("/")
@@ -306,7 +312,7 @@ def read_root():
@app.get("/items/{item_id}") @app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None): def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q} return {"item_id": item_id, "q": q}

View File

@@ -189,7 +189,7 @@ Siehe Abschnitt `### Links` im allgemeinen Prompt in `scripts/translate.py`.
//// ////
## HTML-„abbr“-Elemente { #html-abbr-elements } ## HTML „abbr“-Elemente { #html-abbr-elements }
//// tab | Test //// tab | Test

View File

@@ -56,19 +56,19 @@ from app.routers import items
Die gleiche Dateistruktur mit Kommentaren: Die gleiche Dateistruktur mit Kommentaren:
```bash ```
. .
├── app # "app" ist ein Python-Package ├── app # app ist ein Python-Package
│   ├── __init__.py # diese Datei macht "app" zu einem "Python-Package" │   ├── __init__.py # diese Datei macht app zu einem Python-Package
│   ├── main.py # "main"-Modul, z. B. import app.main │   ├── main.py # main-Modul, z. B. import app.main
│   ├── dependencies.py # "dependencies"-Modul, z. B. import app.dependencies │   ├── dependencies.py # dependencies-Modul, z. B. import app.dependencies
│   └── routers # "routers" ist ein "Python-Subpackage" │   └── routers # routers ist ein Python-Subpackage
│   │ ├── __init__.py # macht "routers" zu einem "Python-Subpackage" │   │ ├── __init__.py # macht routers zu einem Python-Subpackage
│   │ ├── items.py # "items"-Submodul, z. B. import app.routers.items │   │ ├── items.py # items-Submodul, z. B. import app.routers.items
│   │ └── users.py # "users"-Submodul, z. B. import app.routers.users │   │ └── users.py # users-Submodul, z. B. import app.routers.users
│   └── internal # "internal" ist ein "Python-Subpackage" │   └── internal # internal ist ein Python-Subpackage
│   ├── __init__.py # macht "internal" zu einem "Python-Subpackage" │   ├── __init__.py # macht internal zu einem Python-Subpackage
│   └── admin.py # "admin"-Submodul, z. B. import app.internal.admin │   └── admin.py # admin-Submodul, z. B. import app.internal.admin
``` ```
## `APIRouter` { #apirouter } ## `APIRouter` { #apirouter }
@@ -479,7 +479,7 @@ $ fastapi dev app/main.py
</div> </div>
Und öffnen Sie die Dokumentation unter <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>. und öffnen Sie die Dokumentation unter <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Sie sehen die automatische API-Dokumentation, einschließlich der Pfade aller Submodule, mit den richtigen Pfaden (und Präfixen) und den richtigen Tags: Sie sehen die automatische API-Dokumentation, einschließlich der Pfade aller Submodule, mit den richtigen Pfaden (und Präfixen) und den richtigen Tags:

View File

@@ -6,13 +6,29 @@ For that, you can use the `WSGIMiddleware` and use it to wrap your WSGI applicat
## Using `WSGIMiddleware` { #using-wsgimiddleware } ## Using `WSGIMiddleware` { #using-wsgimiddleware }
You need to import `WSGIMiddleware`. /// info
This requires installing `a2wsgi` for example with `pip install a2wsgi`.
///
You need to import `WSGIMiddleware` from `a2wsgi`.
Then wrap the WSGI (e.g. Flask) app with the middleware. Then wrap the WSGI (e.g. Flask) app with the middleware.
And then mount that under a path. And then mount that under a path.
{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *} {* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *}
/// note
Previously, it was recommended to use `WSGIMiddleware` from `fastapi.middleware.wsgi`, but it is now deprecated.
Its advised to use the `a2wsgi` package instead. The usage remains the same.
Just ensure that you have the `a2wsgi` package installed and import `WSGIMiddleware` correctly from `a2wsgi`.
///
## Check it { #check-it } ## Check it { #check-it }

View File

@@ -145,6 +145,8 @@ There are other formats and tools to define and install package dependencies.
* Create a `main.py` file with: * Create a `main.py` file with:
```Python ```Python
from typing import Union
from fastapi import FastAPI from fastapi import FastAPI
app = FastAPI() app = FastAPI()
@@ -156,7 +158,7 @@ def read_root():
@app.get("/items/{item_id}") @app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None): def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q} return {"item_id": item_id, "q": q}
``` ```

View File

@@ -161,6 +161,8 @@ $ pip install "fastapi[standard]"
Create a file `main.py` with: Create a file `main.py` with:
```Python ```Python
from typing import Union
from fastapi import FastAPI from fastapi import FastAPI
app = FastAPI() app = FastAPI()
@@ -172,7 +174,7 @@ def read_root():
@app.get("/items/{item_id}") @app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None): def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q} return {"item_id": item_id, "q": q}
``` ```
@@ -181,7 +183,9 @@ def read_item(item_id: int, q: str | None = None):
If your code uses `async` / `await`, use `async def`: If your code uses `async` / `await`, use `async def`:
```Python hl_lines="7 12" ```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI from fastapi import FastAPI
app = FastAPI() app = FastAPI()
@@ -193,7 +197,7 @@ async def read_root():
@app.get("/items/{item_id}") @app.get("/items/{item_id}")
async def read_item(item_id: int, q: str | None = None): async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q} return {"item_id": item_id, "q": q}
``` ```
@@ -284,7 +288,9 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
Declare the body using standard Python types, thanks to Pydantic. Declare the body using standard Python types, thanks to Pydantic.
```Python hl_lines="2 7-10 23-25" ```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI from fastapi import FastAPI
from pydantic import BaseModel from pydantic import BaseModel
@@ -294,7 +300,7 @@ app = FastAPI()
class Item(BaseModel): class Item(BaseModel):
name: str name: str
price: float price: float
is_offer: bool | None = None is_offer: Union[bool, None] = None
@app.get("/") @app.get("/")
@@ -303,7 +309,7 @@ def read_root():
@app.get("/items/{item_id}") @app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None): def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q} return {"item_id": item_id, "q": q}

View File

@@ -35,11 +35,3 @@ It can be imported from `fastapi`:
```python ```python
from fastapi.middleware.trustedhost import TrustedHostMiddleware from fastapi.middleware.trustedhost import TrustedHostMiddleware
``` ```
::: fastapi.middleware.wsgi.WSGIMiddleware
It can be imported from `fastapi`:
```python
from fastapi.middleware.wsgi import WSGIMiddleware
```

View File

@@ -18,8 +18,6 @@ hide:
### Translations ### Translations
* 🌐 Update translations for de (update-outdated). PR [#14690](https://github.com/fastapi/fastapi/pull/14690) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update LLM prompt for Russian translations. PR [#14733](https://github.com/fastapi/fastapi/pull/14733) by [@YuriiMotov](https://github.com/YuriiMotov).
* 🌐 Update translations for ru (update-outdated). PR [#14693](https://github.com/fastapi/fastapi/pull/14693) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ru (update-outdated). PR [#14693](https://github.com/fastapi/fastapi/pull/14693) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update translations for pt (update-outdated). PR [#14724](https://github.com/fastapi/fastapi/pull/14724) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for pt (update-outdated). PR [#14724](https://github.com/fastapi/fastapi/pull/14724) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update Korean LLM prompt. PR [#14740](https://github.com/fastapi/fastapi/pull/14740) by [@hard-coders](https://github.com/hard-coders). * 🌐 Update Korean LLM prompt. PR [#14740](https://github.com/fastapi/fastapi/pull/14740) by [@hard-coders](https://github.com/hard-coders).

View File

@@ -102,16 +102,15 @@ Of course, you can also declare additional query parameters whenever you need, a
As, by default, singular values are interpreted as query parameters, you don't have to explicitly add a `Query`, you can just do: As, by default, singular values are interpreted as query parameters, you don't have to explicitly add a `Query`, you can just do:
```Python
q: str | None = None
```
Or in Python 3.9:
```Python ```Python
q: Union[str, None] = None q: Union[str, None] = None
``` ```
Or in Python 3.10 and above:
```Python
q: str | None = None
```
For example: For example:

View File

@@ -90,12 +90,5 @@ For the following technical terms, use these specific translations to ensure con
* serve (meaning providing access to something): «отдавать» (or `предоставлять доступ к`) * serve (meaning providing access to something): «отдавать» (or `предоставлять доступ к`)
* recap (noun): резюме * recap (noun): резюме
* utility function: вспомогательная функция * utility function: вспомогательная функция
* fast to code: позволяет быстро писать код
* Tutorial - User Guide: Учебник - Руководство пользователя
* submodule: подмодуль
* subpackage: подпакет
* router: роутер
* building, deploying, accessing (when describing features of FastAPI Cloud): созданиe образа, развертывание и доступ
* type checker tool: инструмент проверки типов
Do not add whitespace in `т.д.`, `т.п.`. Do not add whitespace in `т.д.`, `т.п.`.

View File

@@ -1,5 +1,5 @@
from a2wsgi import WSGIMiddleware
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware.wsgi import WSGIMiddleware
from flask import Flask, request from flask import Flask, request
from markupsafe import escape from markupsafe import escape

View File

@@ -1 +1,3 @@
from starlette.middleware.wsgi import WSGIMiddleware as WSGIMiddleware # noqa from starlette.middleware.wsgi import (
WSGIMiddleware as WSGIMiddleware,
) # pragma: no cover # noqa

View File

@@ -178,6 +178,7 @@ tests = [
"strawberry-graphql>=0.200.0,<1.0.0", "strawberry-graphql>=0.200.0,<1.0.0",
"types-orjson==3.6.2", "types-orjson==3.6.2",
"types-ujson==5.10.0.20240515", "types-ujson==5.10.0.20240515",
"a2wsgi>=1.9.0,<=2.0.0",
] ]
translations = [ translations = [
"gitpython==3.1.45", "gitpython==3.1.45",

16
uv.lock generated
View File

@@ -7,6 +7,18 @@ resolution-markers = [
"python_full_version < '3.10'", "python_full_version < '3.10'",
] ]
[[package]]
name = "a2wsgi"
version = "1.10.10"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/9a/cb/822c56fbea97e9eee201a2e434a80437f6750ebcb1ed307ee3a0a7505b14/a2wsgi-1.10.10.tar.gz", hash = "sha256:a5bcffb52081ba39df0d5e9a884fc6f819d92e3a42389343ba77cbf809fe1f45", size = 18799, upload-time = "2025-06-18T09:00:10.843Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/02/d5/349aba3dc421e73cbd4958c0ce0a4f1aa3a738bc0d7de75d2f40ed43a535/a2wsgi-1.10.10-py3-none-any.whl", hash = "sha256:d2b21379479718539dc15fce53b876251a0efe7615352dfe49f6ad1bc507848d", size = 17389, upload-time = "2025-06-18T09:00:09.676Z" },
]
[[package]] [[package]]
name = "ag-ui-protocol" name = "ag-ui-protocol"
version = "0.1.10" version = "0.1.10"
@@ -1058,6 +1070,7 @@ standard-no-fastapi-cloud-cli = [
[package.dev-dependencies] [package.dev-dependencies]
dev = [ dev = [
{ name = "a2wsgi" },
{ name = "anyio", extra = ["trio"] }, { name = "anyio", extra = ["trio"] },
{ name = "black" }, { name = "black" },
{ name = "cairosvg" }, { name = "cairosvg" },
@@ -1131,6 +1144,7 @@ github-actions = [
{ name = "smokeshow" }, { name = "smokeshow" },
] ]
tests = [ tests = [
{ name = "a2wsgi" },
{ name = "anyio", extra = ["trio"] }, { name = "anyio", extra = ["trio"] },
{ name = "coverage", version = "7.10.7", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.10'" }, { name = "coverage", version = "7.10.7", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.10'" },
{ name = "coverage", version = "7.13.1", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" }, { name = "coverage", version = "7.13.1", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" },
@@ -1197,6 +1211,7 @@ provides-extras = ["standard", "standard-no-fastapi-cloud-cli", "all"]
[package.metadata.requires-dev] [package.metadata.requires-dev]
dev = [ dev = [
{ name = "a2wsgi", specifier = ">=1.9.0,<=2.0.0" },
{ name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" }, { name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" },
{ name = "black", specifier = "==25.1.0" }, { name = "black", specifier = "==25.1.0" },
{ name = "cairosvg", specifier = "==2.8.2" }, { name = "cairosvg", specifier = "==2.8.2" },
@@ -1266,6 +1281,7 @@ github-actions = [
{ name = "smokeshow", specifier = ">=0.5.0" }, { name = "smokeshow", specifier = ">=0.5.0" },
] ]
tests = [ tests = [
{ name = "a2wsgi", specifier = ">=1.9.0,<=2.0.0" },
{ name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" }, { name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" },
{ name = "coverage", extras = ["toml"], specifier = ">=6.5.0,<8.0" }, { name = "coverage", extras = ["toml"], specifier = ">=6.5.0,<8.0" },
{ name = "dirty-equals", specifier = "==0.9.0" }, { name = "dirty-equals", specifier = "==0.9.0" },