DynamicForms FastAPI Viewsets
Django REST Framework-style viewsets for FastAPI, with optional Celery-backed async execution and a matching Vue/TypeScript client counterpart.
- Python mixins for FastAPI — compose CRUD and bulk endpoints from small, focused mixin classes.
route_viewsetdecorator — register a viewset on a FastAPI router with a single decorator call. Handles type resolution, lifecycle management and OpenAPI schema automatically.CollectionViewSet— zero-boilerplate in-memory viewset backed by any Python list, set or dict. Great for prototyping and testing.DjangoORMViewSet— back a viewset with a Django QuerySet. The filters it can compile, the sort order with its NULL placement, the page as LIMIT/OFFSET and the total asCOUNT(*)all become SQL; a stage it declines falls back to the in-memory pass instead of failing, andpk_field_namecomes from the model's primary key (requires thedjangoextra).celery_viewsetdecorator — move a viewset's execution to a Celery worker with no code changes to the viewset itself, for long-running or background processing scenarios (requires theceleryextra).- Bulk operations — first-class support for bulk create, update, partial update and destroy.
- muxws transport — reach the same viewsets over a single WebSocket instead of one HTTP request per call. A command goes through your application as an HTTP request does - its middleware, exception handlers, router dependencies and state - so both transports behave identically. In the demo, a burst of 100 requests takes 156 ms over REST and 37 ms over muxws.
- Events — publish an event to a topic and every frontend following it learns of it, as a muxws
push or on its next poll.
ChangeEventspublishes every create, update and destroy of a viewset to its routed base path; custom events are declared withsource(). Every event is recorded before it is pushed, so a dropped push costs latency, not an event. On the frontend,watch()on a ViewSet follows its topic andapplyChanges()applies each change to a list of rows. - Three list shapes — a bare array, offset paging, or cursor paging. A viewset declares which,
and may let a client pick per request with an
X-List-Shapeheader. - Declarative filters — declare which fields accept which operators and get query parameters, an OpenAPI schema and filtering for free; backends translate what they can into their own query.
- Vue / TypeScript counterpart — mirror mixin classes and the
restViewSet/muxwsViewSetclass factory give you a fully typed client that matches your backend viewset exactly: the mixins a ViewSet declares are its public surface, so calling an action it did not declare is a compile error rather than a runtime 404 (published separately as@dynamicforms/fastapi-viewsetson npm).
Installation
pip install dynamicforms-fastapi-viewsets
# with Celery-backed viewset support
pip install "dynamicforms-fastapi-viewsets[celery]"
# with the muxws WebSocket transport
pip install "dynamicforms-fastapi-viewsets[muxws]"
# with the Django ORM backend (Django 4.2+ and asgiref)
pip install "dynamicforms-fastapi-viewsets[django]"
Requires Python 3.10+, FastAPI and Pydantic 2.11+.
Quick example
from fastapi import APIRouter, FastAPI
from pydantic import BaseModel
from fastapi_viewsets.collection_viewset import CollectionViewSet
from fastapi_viewsets.decorators.route_viewset import route_viewset
from fastapi_viewsets.mixins import BulkViewSetMixin
class Item(BaseModel):
id: int
name: str
database: dict[int, Item] = {1: Item(id=1, name="First element")}
app = FastAPI()
router = APIRouter()
@route_viewset(router, base_path="/items", pk_field_name="id")
class ItemViewSet(CollectionViewSet[int, Item], BulkViewSetMixin[int, Item]):
def __init__(self):
super().__init__(container=database, pk_field="id")
app.include_router(router)
See the full documentation for guides on
the mixin system, route_viewset, CollectionViewSet, DjangoORMViewSet, celery_viewset, the
list pipeline and pagination, the muxws transport, and the Vue client.
Demo
python demo.py # backend on :8000, frontend on :5173
python demo.py --celery # ... with every viewset call routed through a Celery worker
npm run test:e2e # drives the demo in a browser
An infinite-scrolling grid over a 5000-track library, cursor-paged. Switch the whole grid between the REST and muxws transports and between the in-memory and SQLite backends, and compare their latency side by side. Sorting and filtering are server-side.
The grid follows its viewset's change events (ChangeEvents on the backend, watch() in the
grid). Click a Favorite cell to toggle it: every tab showing the library applies the change, over
muxws as a push, over REST on its next poll. A sorted or filtered grid reloads its list on the
change: the row may have moved or left it.
--celery needs Redis on localhost:6379. The worker runs the viewset calls of both backends and
publishes their events through Redis. It runs as one process, because the in-memory library is a
dict held by each process; the SQLite library is one file shared by every process. The end-to-end
suite starts its own backend and dev server on their own ports.
License
MIT — see LICENSE.
Metadata
Release files for dynamicforms-fastapi-viewsets 0.10.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| dynamicforms_fastapi_viewsets-0.10.0.tar.gz | 121.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dynamicforms_fastapi_viewsets-0.10.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 277.3 kB
Release files / dynamicforms_fastapi_viewsets-0.10.0.tar.gz
| Download URL | dynamicforms_fastapi_viewsets-0.10.0.tar.gz |
|---|---|
| Size | 121.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7321113c41a44f2ca3d1c8e83804a54f88c4873e33524977ea9c58a03f65ccbe
|
|
BLAKE2b-256 checksum How to use checksums |
efe8fddbbf50788555ca4c8d4b79e4b6d9e250b0f9c37d9f81f52ca365bd4110
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.2
|
Release files / dynamicforms_fastapi_viewsets-0.10.0-py3-none-any.whl
| Download URL | dynamicforms_fastapi_viewsets-0.10.0-py3-none-any.whl |
|---|---|
| Size | 155.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4a37165b10e86b9d6fa876d117bf1158a25707ac2aaedc584ef1663fe2859f26
|
|
BLAKE2b-256 checksum How to use checksums |
b6ada9aaa48c80d6d3ff2458f97b85bc9fb49392372bd36ec37c1c4447a6bb1d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.2
|