Skip to main content

ModelAdmin

Trait ModelAdmin 

Source
pub trait ModelAdmin: AdminModel {
    // Provided methods
    fn list_display() -> &'static [&'static str] { ... }
    fn list_filter() -> &'static [&'static str] { ... }
    fn search_fields() -> &'static [&'static str] { ... }
    fn ordering() -> &'static [&'static str] { ... }
    fn list_per_page() -> usize { ... }
    fn readonly_fields() -> &'static [&'static str] { ... }
    fn fieldsets() -> &'static [Fieldset] { ... }
    fn bulk_actions() -> &'static [BulkAction] { ... }
    fn execute_bulk_action<'a>(
        action: &'a str,
        _ids: &'a [i64],
        _db: &'a Db,
        _ctx: &'a BulkActionContext<'a>,
    ) -> Pin<Box<dyn Future<Output = Result<BulkActionResult>> + Send + 'a>> { ... }
}
Expand description

Django-style customisation surface for a registered admin model.

Every type that implements AdminModel gets a default impl via the blanket below. Override the methods you care about; everything else inherits sensible defaults.

Provided Methods§

Source

fn list_display() -> &'static [&'static str]

Columns shown on the list page, in order. Default: every field declared on AdminModel::FIELDS.

Returning &[] means “use the model’s full field list” — the list page expands the empty default into M::FIELDS. Any non-empty slice replaces the defaults verbatim.

Source

fn list_filter() -> &'static [&'static str]

Columns offered as filter chips in the sidebar. Default: none.

Source

fn search_fields() -> &'static [&'static str]

Columns searched by the list-page search box (case-insensitive substring match). Default: none.

Source

fn ordering() -> &'static [&'static str]

Default ordering. -foo for foo DESC, foo for foo ASC. Multiple entries → multi-column ORDER BY in slice order. Default: ["-id"] (newest first).

Source

fn list_per_page() -> usize

Rows per page on the list view. Default: 50.

Source

fn readonly_fields() -> &'static [&'static str]

Read-only fields on the change form. Default: none.

Source

fn fieldsets() -> &'static [Fieldset]

Field grouping on the change form. Default: empty — fall back to the framework heuristic (Default / System / Advanced).

Source

fn bulk_actions() -> &'static [BulkAction]

Custom bulk actions surfaced as extra buttons in the list-view bulk bar (next to the framework’s built-in Delete). Default: none.

BulkAction is metadata only — pair this method with an ModelAdmin::execute_bulk_action override that matches on name and applies the work. The framework’s default dispatcher returns a clear BadRequest for any name it doesn’t recognise, so a forgotten implementation surfaces as an error page rather than a silent no-op.

Source

fn execute_bulk_action<'a>( action: &'a str, _ids: &'a [i64], _db: &'a Db, _ctx: &'a BulkActionContext<'a>, ) -> Pin<Box<dyn Future<Output = Result<BulkActionResult>> + Send + 'a>>

Run a project-defined bulk action against ids. Called once per POST /admin/:model/bulk/:name submission with the full id list — the implementation chooses between a single bulk SQL update and a per-row loop.

The framework wraps this call with one [audit::record] emission per submission (using BulkActionContext.actor, correlation_id, and the BulkActionResult outcome). Projects don’t need to audit the dispatch envelope themselves; any business-level audit emissions inside the action body are still the project’s call.

Two channels for “something went wrong”:

  • Action itself failed — return Err(...). The framework surfaces it as a 4xx/5xx page and still writes an audit row for the attempt.
  • Some rows failed — return Ok(BulkActionResult) with a populated failed list. The framework records a partial-success audit row and renders the per-id failure summary on the next request.

The framework’s built-in delete action does not flow through this method. It runs through the cascade-aware /bulk_delete route. Override delete semantics on the underlying crate::Model / handler layer if you need custom delete behaviour.

The default implementation returns a structured error so a declared-but-unimplemented action surfaces clearly:

use std::future::Future;
use std::pin::Pin;
use rustio_admin::{
    BulkAction, BulkActionContext, BulkActionResult, Db, ModelAdmin, Result,
};

impl ModelAdmin for Loan {
    fn bulk_actions() -> &'static [BulkAction] {
        &[BulkAction {
            name: "mark_overdue",
            label: "Mark overdue",
            destructive: false,
            confirm: true,
        }]
    }

    fn execute_bulk_action<'a>(
        action: &'a str,
        ids: &'a [i64],
        _db: &'a Db,
        _ctx: &'a BulkActionContext<'a>,
    ) -> Pin<Box<dyn Future<Output = Result<BulkActionResult>> + Send + 'a>> {
        Box::pin(async move {
            match action {
                "mark_overdue" => Ok(BulkActionResult::ok(ids.len())),
                _ => Ok(BulkActionResult::default()),
            }
        })
    }
}

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§