Expand description
Generic class-based views for HTML templates —
ListView, DetailView, CreateView, UpdateView, DeleteView over
#[derive(Model)] schemas, rendered with Tera. The HTML sibling of
viewset. Runs on all three backends. See template_views for
usage and the Tera context shape.
Generic class-based views for HTML templates.
Sibling of crate::viewset for the JSON/API side. Each view is a
data structure that builds a Tera-rendered axum Router over a
#[derive(Model)] schema:
| View | What it does | Template default |
|---|---|---|
ListView | Paginated list — ?page=N query param | <table>_list.html |
DetailView | Single row by primary key — /{pk} | <table>_detail.html |
CreateView | GET empty form / POST insert / 303 to success_url | <table>_form.html |
UpdateView | GET prefilled form / POST update / 303 | <table>_form.html |
DeleteView | GET confirm / POST delete / 303 | <table>_confirm_delete.html |
§Quick start
ⓘ
use rustango::template_views::ListView;
use std::sync::Arc;
let mut tera = rustango::template_extensions::html_tera();
tera.add_raw_template("post_list.html", r#"
{% for post in object_list %}
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
{% endfor %}
{% if has_prev %}<a href="?page={{ page - 1 }}">prev</a>{% endif %}
{% if has_next %}<a href="?page={{ page + 1 }}">next</a>{% endif %}
"#).unwrap();
let app = ListView::for_model(Post::SCHEMA)
.page_size(20)
.order_by("created_at", true) // DESC
.router("/posts", Arc::new(tera), pool);§Tera context
Every view stamps a consistent context shape so templates port cleanly between views:
object_list: Vec<Map<String, Value>>— the page’s rows as JSON (nullfor SQL nulls; columns named after the field’scolumn)page: i64— 1-indexed current pagepage_size: i64total: i64— total matching rows across every pagetotal_pages: i64has_next: boolhas_prev: bool
§Pool capture vs per-tenant resolution
Each view ships two router constructors:
.router(prefix, tera, pool)— single-tenant, captures aPgPoolat mount time. Mirrors the originalViewSet::router..tenant_router(prefix, tera)— multi-tenant, resolves a per-request connection via thecrate::extractors::Tenantextractor. Mirrorsviewset::ViewSet::tenant_router. Available behind the combinedtemplate_views+tenancyfeatures.
Same builder API across both flavors; pick whichever matches the project’s connection-management strategy. Templates port between them without edits.
Structs§
- Bulk
Action - One registered bulk action. The framework ships
delete_selectedas a built-in whenListView::bulk_actionsis enabled; user-defined actions wire in viaListView::action(static pool) orListView::tenant_action(per-request tenant connection). - Create
View GET <prefix>/newrenders an empty form,POST <prefix>/newinserts the row and 303s tosuccess_url.- Delete
View - Two-step delete:
GET <prefix>/{pk}/deleterenders a confirmation page,POST <prefix>/{pk}/deleteexecutes the delete and 303s tosuccess_url. - Detail
View - Render a single row of
Mlooked up by primary key. - Extra
Context - Extra template context, supplied per request through an axum
Extension. - Form
View - No-model CBV that renders a
#[derive(Form)]form on GET, parses - List
View - Render a paginated list of rows for
M. - Redirect
View - No-model CBV that returns an HTTP redirect to a fixed URL.
Use for canonical URL migrations (old
/about-us→ new/about), short links, or “click here to go there” flows. Issue #13. - Template
View - No-model CBV that renders a Tera template with a static context. Use for about pages, terms-of-service, dashboards built from context the caller assembles up front.
- Update
View GET <prefix>/{pk}/editrenders a form prefilled from the row;POST <prefix>/{pk}/editupdates the row and 303s tosuccess_url.
Enums§
- Bulk
Action Handler - Either a static-pool handler or a tenant-mode handler. Built up
by the builder methods and dispatched in the matching POST
handler. Mixing kinds on the same
ListViewdoesn’t make sense (the router only mounts one handler shape), so the wrong-kind case surfaces a clear runtime error rather than corrupting the connection.
Type Aliases§
- Bulk
Action Fn - Handler closure for a bulk action mounted on the static-pool
ListView::routerpath. Receives the captured&Pooland the parsed list of selected primary keys (already type-coerced from the form’s_selected_actionstrings). - Bulk
Action Future - Future returned by a
ListViewbulk action handler. Mirrors the shapeadmin::AdminActionFutureuses so handlers feel consistent across the framework. Errors render as a 400 response with the supplied string in the body. - Tenant
Bulk Action Fn - Tenant-mode counterpart — runs against the per-request tenant
connection from
crate::extractors::Tenant::conn. Wired viaListView::tenant_action. v0.38 — PG-only by signature (takes&mut PgConnection). Sqlite/ MySQL tenants get the tri-dialectPool-based variantTenantBulkActionPoolFnbelow. - Tenant
Bulk Action Pool Fn - Tri-dialect tenant-mode bulk-action handler — runs against the
per-request tenant
Poolfromcrate::extractors::Tenant::poolso the handler works on Postgres, MySQL, and SQLite tenants uniformly. Wired viaListView::tenant_action_pool. - Validator
- User-supplied validation hook installed on
CreateView/UpdateViewviaCreateView::validator/UpdateView::validator(or theForm-trait convenienceCreateView::form/UpdateView::form). Runs after schema-level type coercion + max_length / min / max bounds (which the framework owns) but before the SQL INSERT/UPDATE. ReturningErr(FormErrors)re-renders the form with the merged error map and a 422 status.