Class-based views for FastAPI routers — a maintained, FastAPI 0.137+ compatible drop-in for fastapi_utils.cbv.
Project description
fastapi-cbv-router
Class-based views (CBV) for FastAPI routers — a small, maintained drop-in
replacement for the unmaintained fastapi_utils.cbv. Works on modern FastAPI
(tested from 0.115), and in particular survives FastAPI 0.137+, where
fastapi_utils.cbv breaks.
Why
fastapi_utils.cbv relied on APIRouter.include_router eagerly copying
APIRoute objects into router.routes. FastAPI 0.137 made include_router
lazy, which broke fastapi_utils whenever two @cbv decorators shared one
router.
fastapi-cbv-router rebuilds each endpoint through the router's public
add_api_route / add_api_websocket_route API, which stays eager and
delegates all route-state computation back to FastAPI. Route configuration is
copied by introspecting add_api_route's own parameters, so the package adapts
to upstream FastAPI changes instead of hard-coding a kwarg list.
Features
- One small decorator,
@cbv(router)— no base classes or metaclasses required. - Share a single dependency instance (
self) across every endpoint on a class. - Inject dependencies either as class-level annotated attributes or through a
custom
__init__— use whichever fits your style. - Works with regular HTTP routes and WebSocket routes.
- Preserves all route configuration (
status_code,response_model,dependencies, tags, …) and the routerprefix. - Fully typed (
py.typed), zero dependencies beyond FastAPI.
Requirements
- Python: 3.13+
- FastAPI: 0.115+ — continuously tested against the latest release, currently
0.137.2. The test suite specifically covers FastAPI 0.137+, where
include_routerbecame lazy and brokefastapi_utils.cbv.
Install
pip install fastapi-cbv-router
# or
uv add fastapi-cbv-router
Quickstart
from fastapi import APIRouter, Depends, FastAPI
from fastapi_cbv_router import cbv
router = APIRouter(prefix="/items")
def get_db() -> str:
return "db-connection"
@cbv(router)
class ItemsView:
db: str = Depends(get_db)
@router.get("/")
def list_items(self) -> dict:
return {"db": self.db, "items": []}
@router.post("/")
def create_item(self, name: str) -> dict:
return {"db": self.db, "created": name}
app = FastAPI()
app.include_router(router)
Class-level annotated attributes become keyword-only dependencies injected via
Depends(ItemsView) and are available as self.<attr> in every endpoint.
ClassVar-annotated attributes are treated as plain class constants and are not
injected.
Dependency injection via __init__
If you prefer constructor injection — for example to keep a clean abstract base
and wire dependencies explicitly — define a custom __init__. Its parameters
are resolved by FastAPI when the view is constructed, exactly like an endpoint's
parameters:
import abc
from http import HTTPStatus
from fastapi import APIRouter, Depends
from fastapi_cbv_router import cbv
router = APIRouter(prefix="/items", tags=["items"])
def get_service() -> "ItemService":
...
class ItemApi(abc.ABC):
@abc.abstractmethod
async def get_item(self, item_id: int) -> dict: ...
@cbv(router)
class HttpItemApi(ItemApi):
def __init__(self, service: "ItemService" = Depends(get_service)) -> None:
self.service = service
@router.get("/{item_id}", status_code=HTTPStatus.OK)
async def get_item(self, item_id: int) -> dict:
return await self.service.fetch(item_id)
This pairs cleanly with DI containers such as
dependency-injector: use
Depends(Provide[...]) defaults on the @inject-decorated __init__.
WebSocket routes
WebSocket endpoints are supported the same way as HTTP routes:
from fastapi import APIRouter, WebSocket
from fastapi_cbv_router import cbv
router = APIRouter()
@cbv(router)
class ChatView:
@router.websocket("/ws")
async def chat(self, websocket: WebSocket) -> None:
await websocket.accept()
await websocket.send_text("hello")
await websocket.close()
Scope
Only the plain @cbv(router) form is supported (no *urls / set_responses
helpers). This is intentional — it covers the common case with the smallest,
most maintainable surface.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fastapi_cbv_router-0.1.0.tar.gz.
File metadata
- Download URL: fastapi_cbv_router-0.1.0.tar.gz
- Upload date:
- Size: 6.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.22 {"installer":{"name":"uv","version":"0.11.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc1b2e6a4a5cdbb9236cb146cc54feb4d234757928fe3a46c46e7bc46ca45a1c
|
|
| MD5 |
9a62510a2ef2957f2bf8a5b60836a05f
|
|
| BLAKE2b-256 |
78a451e4abbaf11f711d42da194ae74dfc5ff27068ee26f3cc2a1acacf54569b
|
File details
Details for the file fastapi_cbv_router-0.1.0-py3-none-any.whl.
File metadata
- Download URL: fastapi_cbv_router-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.22 {"installer":{"name":"uv","version":"0.11.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1600f8a6d7eca9d5a62c186ea90bc2e4195e00abc6cbf70084e4777adc5ed343
|
|
| MD5 |
c71b4e78ca0299387d1e3c4f7145a2bc
|
|
| BLAKE2b-256 |
15fc691db01206e65d7bca33f52cd273d7d33727e3d9b7f0405cd59ca5dd17e8
|