You are reading the docs for rws 18.35 The latest release is 18.36. Read this page for the latest release.

Model admin

Pages to list, search, create, edit and delete database rows — Django's admin for rws, as one middleware.

model_admin::ModelAdmin gives the tables you register pages to list, search, show, create, edit and delete rows — Django's admin, for a DbPool (any model-* feature). It's a middleware, so it works in front of sync and async apps alike (18.35.0).

use rust_web_server::auth_flows::CurrentUser;
use rust_web_server::model_admin::ModelAdmin;

let admins = ["ann@example.com".to_string()];
let admin = ModelAdmin::new(pool.clone())
    .title("Notes admin")
    .model::<Note>()                         // its #[table] name
    .table("rws_users")                      // or a table by name
    .allow(move |request| CurrentUser::of(request).is_some_and(|u| admins.contains(&u.email)));

// The first layer wrapped is the outermost.
let site = app(pool)
    .wrap(FlashLayer::new())                 // clears the messages the admin pages show
    .wrap(auth)                              // AuthFlows: who's asking
    .wrap(admin);

Nobody gets in until allow says so: without it every admin page answers 403. The check runs for each request, after the layers outside the admin — wrap it after AuthFlows (inside it) to use CurrentUser, and after FlashLayer and CsrfLayer (whose token the forms carry).

Pages

Path Page
/admin The tables, with their row counts
/admin/<table>?q=&page= 25 rows a page, newest key first; q searches the text columns (case-insensitive)
/admin/<table>/new, POST /admin/<table> A new row
/admin/<table>/<id> One row
/admin/<table>/<id>/edit, POST /admin/<table>/<id> Change it
POST /admin/<table>/<id>/delete Delete it

.prefix("/backoffice") moves them. Only registered tables are served; table names are letters, digits and _.

How it reads the database

The columns, their types and the primary key come from the database itself (DbPool::schema) each time a page is drawn, so a migration shows at once — no admin code per model. Form values are converted by the column's type: integers and floats are checked, a BOOLEAN column is a checkbox, an empty field is NULL for a nullable column; created_at / updated_at are set to now when the form leaves them empty. On an edit, a column the form doesn't send keeps its value. What the database refuses — NOT NULL, a unique index, a foreign key — comes back as an alert on the form, through a flash message (add FlashLayer).

A table needs a one-column primary key to be edited; others are listed only. An integer key is left to the database when creating a row; any other key is a form field. On SQLite a column declared INTEGER is a number field even when it holds booleans (declare it BOOLEAN for a checkbox).

Values are shown as text and escaped; long ones are cut to 80 characters in the list. The pages are plain HTML with a little inline CSS and no scripts beyond a delete confirmation.

Edit this page on GitHub