Expand description
DRF-style ModelViewSet — five REST endpoints for any Model table
in ~5 lines. See viewset::ViewSet.
v0.38 — fully tri-dialect. Internal queries route through
select_rows_as_json + insert_returning_pool etc., so the
same ViewSet body runs on PG / MySQL / SQLite. v0.45 — the
.serializer() render extension is tri-dialect too: it fetches
typed Vec<S::Model> via select_rows_pool_with_related (which
decodes on every backend) and renders list / retrieve / create
responses through S::from_model, so the serializer’s shape
applies on PG, MySQL and SQLite.
The router(prefix, &PgPool) (static-pool) entry point keeps its
PG-typed pool arg for source-compat; tenant_router(prefix)
works on every dialect via the generic Tenant#[cfg(feature = "tenancy")]-gated inside the
module; the static-pool CRUD ViewSet needs only admin — the
feature that pulls axum into the dep graph). Available under
either admin or tenancy so the fullstack template (admin, no
tenancy) gets the CRUD ViewSet while tenant projects keep the
tenant_router path.
Django REST Framework–style router viewsets.
A ViewSet wires five standard REST endpoints for any Model
table in ~5 lines. No hand-written handlers, no SQL, no repetition.
§Quick start
use rustango::viewset::ViewSet;
// In your router setup:
let posts_router = ViewSet::for_model(Post::SCHEMA)
.fields(&["id", "title", "body", "author_id", "published_at"])
.filter_fields(&["author_id"])
.search_fields(&["title", "body"])
.ordering(&[("published_at", true)]) // DESC by default
.page_size(20)
.router("/api/posts", pool.clone());
// Merge into your app router:
let app = Router::new().merge(posts_router);§Endpoints
| Method | Path | Action |
|---|---|---|
GET | /api/posts | List — {"count": N, "results": [...]} |
POST | /api/posts | Create — returns the new object |
GET | /api/posts/{pk} | Retrieve — single object |
PUT | /api/posts/{pk} | Update — full replace |
PATCH | /api/posts/{pk} | Partial update — only supplied fields |
DELETE | /api/posts/{pk} | Delete — 204 No Content |
§Query parameters (list endpoint)
§Page-number pagination (default)
| Parameter | Default | Description |
|---|---|---|
page | 1 | 1-based page number |
page_size | configured default | Items per page (capped at 1000) |
ordering | configured default | Comma-separated field names, prefix - for DESC |
search | — | Full-text search across search_fields |
{field} | — | Exact filter for any filter_fields |
{field}__{lookup} | — | Django-style lookup (gt/gte/lt/lte/ne/in/not_in/contains/icontains/startswith/istartswith/endswith/iendswith/isnull) |
Response: {"count": N, "page": P, "page_size": S, "last_page": L, "results": [...]}
§Cursor pagination (opt-in)
Enable via .cursor_pagination("id") or .cursor_pagination_desc("id").
Skips the COUNT(*) query so it scales to billion-row tables.
| Parameter | Default | Description |
|---|---|---|
cursor | — | Opaque token from a previous response’s next field |
page_size | configured default | Items per page (capped at 1000) |
{field} | — | Exact filter for any filter_fields |
Response: {"page_size": S, "next": "<token>" \| null, "results": [...]}
§Limit/offset pagination (opt-in)
Enable via .limit_offset_pagination(). DRF-shape ?limit=&offset=
windowing — handy for tables/grids that page by row offset rather
than page number. Runs COUNT(*) per request (same cost as
page-number).
| Parameter | Default | Description |
|---|---|---|
limit | configured default | Items to return (capped at 1000) |
offset | 0 | Rows to skip before the window |
ordering | configured default | Comma-separated field names, prefix - for DESC |
search | — | Full-text search across search_fields |
{field} | — | Exact filter for any filter_fields |
Response: {"count": N, "limit": L, "offset": O, "results": [...]}
§Permissions
Pair with RouterAuthExt
on the outer router to require auth, then pass codenames to .permissions():
ViewSet::for_model(Post::SCHEMA)
.permissions(ViewSetPerms {
list: vec!["post.view"],
retrieve: vec!["post.view"],
create: vec!["post.add"],
update: vec!["post.change"],
destroy: vec!["post.delete"],
})
.router("/api/posts", pool.clone())Structs§
- Throttle
Rule - A fixed-window throttle limit — at most
maxrequests perwindow_secs(DRFScopedRateThrottleshape, #1010). - ViewSet
- Builder for a set of REST CRUD endpoints over a single [
Model] table. - View
SetPerms - Permission codenames required for each ViewSet action.
- View
SetThrottle - Per-action request throttles for a ViewSet (DRF
throttle_classesparity, #1010). Any action leftNoneis unthrottled.
Enums§
- Pagination
Style - Pagination strategy for ViewSet list endpoints.
Traits§
- View
SetFilter - A pluggable filter backend (DRF
BaseFilterBackendparity, #1010).