pub trait AdminModel:
Send
+ Sync
+ 'static {
Show 25 methods
// Required methods
fn slug(&self) -> &'static str;
fn display_name(&self) -> &'static str;
fn display_name_plural(&self) -> &'static str;
fn fields(&self) -> Vec<AdminField>;
fn list(
&self,
pool: &Pool<AsyncPgConnection>,
params: ListParams,
) -> AdminFuture<'_, ListResult>;
fn get(
&self,
pool: &Pool<AsyncPgConnection>,
id: i64,
) -> AdminFuture<'_, Option<Value>>;
fn create(
&self,
pool: &Pool<AsyncPgConnection>,
data: Value,
) -> AdminFuture<'_, Value>;
fn update(
&self,
pool: &Pool<AsyncPgConnection>,
id: i64,
data: Value,
) -> AdminFuture<'_, Value>;
fn delete(
&self,
pool: &Pool<AsyncPgConnection>,
id: i64,
) -> AdminFuture<'_, ()>;
// Provided methods
fn actions(&self) -> Vec<AdminAction> { ... }
fn supports_soft_delete(&self) -> bool { ... }
fn restore<'a>(
&'a self,
_pool: &'a Pool<AsyncPgConnection>,
_id: i64,
) -> AdminFuture<'a, ()> { ... }
fn purge<'a>(
&'a self,
_pool: &'a Pool<AsyncPgConnection>,
_id: i64,
) -> AdminFuture<'a, ()> { ... }
fn list_deleted<'a>(
&'a self,
_pool: &'a Pool<AsyncPgConnection>,
_params: ListParams,
) -> AdminFuture<'a, ListResult> { ... }
fn execute_action(
&self,
pool: &Pool<AsyncPgConnection>,
action: &str,
ids: Vec<i64>,
) -> AdminFuture<'_, u64> { ... }
fn record_display(&self, record: &Value) -> String { ... }
fn per_page(&self) -> u64 { ... }
fn count(&self, pool: &Pool<AsyncPgConnection>) -> AdminFuture<'_, u64> { ... }
fn supports_csv_export(&self) -> bool { ... }
fn csv_export_columns(&self) -> Vec<&'static str> { ... }
fn csv_export_row(&self, columns: &[&str], record: &Value) -> Vec<String> { ... }
fn supports_csv_import(&self) -> bool { ... }
fn import_csv_row<'a>(
&'a self,
_pool: &'a Pool<AsyncPgConnection>,
_line: u64,
_row: HashMap<String, String>,
_mode: CsvImportMode,
) -> AdminFuture<'a, AdminImportRowResult> { ... }
fn has_history(&self) -> bool { ... }
fn get_history<'a>(
&'a self,
_pool: &'a Pool<AsyncPgConnection>,
_record_id: i64,
_page: u64,
_per_page: u64,
) -> AdminFuture<'a, AdminHistoryPage> { ... }
}Expand description
The core trait that enables a model to be managed in the admin panel.
Implementors provide field metadata, CRUD operations, and display configuration. The admin plugin uses this trait to generate all views dynamically at runtime.
§Design notes
All data flows through serde_json::Value to keep the trait object-safe.
The admin panel doesn’t need to know concrete types — it renders fields
based on AdminField metadata and passes values as JSON.
Required Methods§
Sourcefn slug(&self) -> &'static str
fn slug(&self) -> &'static str
URL-safe slug for this model (e.g., “projects”, “tickets”).
Used in admin URLs: /admin/projects/, /admin/projects/42/.
Sourcefn display_name(&self) -> &'static str
fn display_name(&self) -> &'static str
Human-readable singular name (e.g., “Project”).
Sourcefn display_name_plural(&self) -> &'static str
fn display_name_plural(&self) -> &'static str
Human-readable plural name (e.g., “Projects”).
Sourcefn fields(&self) -> Vec<AdminField>
fn fields(&self) -> Vec<AdminField>
Field metadata for this model.
Sourcefn list(
&self,
pool: &Pool<AsyncPgConnection>,
params: ListParams,
) -> AdminFuture<'_, ListResult>
fn list( &self, pool: &Pool<AsyncPgConnection>, params: ListParams, ) -> AdminFuture<'_, ListResult>
List records with pagination, search, sort, and filters.
Sourcefn get(
&self,
pool: &Pool<AsyncPgConnection>,
id: i64,
) -> AdminFuture<'_, Option<Value>>
fn get( &self, pool: &Pool<AsyncPgConnection>, id: i64, ) -> AdminFuture<'_, Option<Value>>
Get a single record by ID.
Sourcefn create(
&self,
pool: &Pool<AsyncPgConnection>,
data: Value,
) -> AdminFuture<'_, Value>
fn create( &self, pool: &Pool<AsyncPgConnection>, data: Value, ) -> AdminFuture<'_, Value>
Create a new record from form data.
Sourcefn update(
&self,
pool: &Pool<AsyncPgConnection>,
id: i64,
data: Value,
) -> AdminFuture<'_, Value>
fn update( &self, pool: &Pool<AsyncPgConnection>, id: i64, data: Value, ) -> AdminFuture<'_, Value>
Update an existing record.
Sourcefn delete(&self, pool: &Pool<AsyncPgConnection>, id: i64) -> AdminFuture<'_, ()>
fn delete(&self, pool: &Pool<AsyncPgConnection>, id: i64) -> AdminFuture<'_, ()>
Delete a record by ID.
Provided Methods§
Sourcefn actions(&self) -> Vec<AdminAction>
fn actions(&self) -> Vec<AdminAction>
Available bulk actions.
Defaults to “Delete selected”. When supports_soft_delete() returns
true, also includes “Restore selected” and “Purge selected” so that
the admin route validator can dispatch those action names.
Sourcefn supports_soft_delete(&self) -> bool
fn supports_soft_delete(&self) -> bool
Whether this model supports soft-delete (defaults to false).
When true, the admin panel shows a Trash tab with restore/purge.
Sourcefn restore<'a>(
&'a self,
_pool: &'a Pool<AsyncPgConnection>,
_id: i64,
) -> AdminFuture<'a, ()>
fn restore<'a>( &'a self, _pool: &'a Pool<AsyncPgConnection>, _id: i64, ) -> AdminFuture<'a, ()>
Restore a soft-deleted record (set deleted_at = NULL).
The default returns AdminError::Other when supports_soft_delete() is
false, so models that opt in must override this method.
Sourcefn purge<'a>(
&'a self,
_pool: &'a Pool<AsyncPgConnection>,
_id: i64,
) -> AdminFuture<'a, ()>
fn purge<'a>( &'a self, _pool: &'a Pool<AsyncPgConnection>, _id: i64, ) -> AdminFuture<'a, ()>
Permanently delete (purge) a soft-deleted record.
The default returns AdminError::Other when supports_soft_delete() is
false.
Sourcefn list_deleted<'a>(
&'a self,
_pool: &'a Pool<AsyncPgConnection>,
_params: ListParams,
) -> AdminFuture<'a, ListResult>
fn list_deleted<'a>( &'a self, _pool: &'a Pool<AsyncPgConnection>, _params: ListParams, ) -> AdminFuture<'a, ListResult>
List soft-deleted records (where deleted_at IS NOT NULL).
The default returns AdminError::Other when supports_soft_delete() is
false.
Sourcefn execute_action(
&self,
pool: &Pool<AsyncPgConnection>,
action: &str,
ids: Vec<i64>,
) -> AdminFuture<'_, u64>
fn execute_action( &self, pool: &Pool<AsyncPgConnection>, action: &str, ids: Vec<i64>, ) -> AdminFuture<'_, u64>
Execute a bulk action on the given IDs.
Sourcefn record_display(&self, record: &Value) -> String
fn record_display(&self, record: &Value) -> String
Return a display string for a record (used in breadcrumbs, titles).
Defaults to "ModelName #id" (or "ModelName <no id>" when the
record has no numeric id).
Sourcefn count(&self, pool: &Pool<AsyncPgConnection>) -> AdminFuture<'_, u64>
fn count(&self, pool: &Pool<AsyncPgConnection>) -> AdminFuture<'_, u64>
Count records matching a list query (defaults to list(..., per_page: 0).total).
Override if the backend can count without materializing records.
Sourcefn supports_csv_export(&self) -> bool
fn supports_csv_export(&self) -> bool
Whether this model exposes a GET /admin/{slug}/export.csv link.
Defaults to false — export must be explicitly opted into to avoid
silently exposing model data on upgrade. Override to true to enable
the CSV export button and route.
Sourcefn csv_export_columns(&self) -> Vec<&'static str>
fn csv_export_columns(&self) -> Vec<&'static str>
Column names written to the CSV header row during export.
Defaults to the ordered names of all non-password, non-hidden fields
declared in fields. Override to add computed columns (e.g. a
joined display value) or to omit sensitive columns (PII redaction).
§PII redaction strategy
To redact a column: remove it from this list. To include a placeholder
instead of the real value, add the column here and override
AdminModel::csv_export_row to return "[REDACTED]" for that key.
Sourcefn csv_export_row(&self, columns: &[&str], record: &Value) -> Vec<String>
fn csv_export_row(&self, columns: &[&str], record: &Value) -> Vec<String>
Serialize a single record (as returned by list) into an ordered
list of string values for CSV export.
The default implementation extracts values for each column in
csv_export_columns from the JSON record. Override to add computed
columns (joined values, formatted timestamps, etc.).
Sourcefn supports_csv_import(&self) -> bool
fn supports_csv_import(&self) -> bool
Whether this model accepts POST /admin/{slug}/import CSV uploads.
Defaults to false — import must be explicitly opted into because it
performs bulk writes. Override to true and implement
import_csv_row to enable the import UI.
Sourcefn import_csv_row<'a>(
&'a self,
_pool: &'a Pool<AsyncPgConnection>,
_line: u64,
_row: HashMap<String, String>,
_mode: CsvImportMode,
) -> AdminFuture<'a, AdminImportRowResult>
fn import_csv_row<'a>( &'a self, _pool: &'a Pool<AsyncPgConnection>, _line: u64, _row: HashMap<String, String>, _mode: CsvImportMode, ) -> AdminFuture<'a, AdminImportRowResult>
Process a single CSV row during an admin import.
Receives the 1-based line number in the CSV file and a map of
column_name → value (all strings; coerce as needed). Return the
appropriate AdminImportRowResult.
The default always returns AdminImportRowResult::Skipped — models
that set supports_csv_import to true should override this.
Sourcefn has_history(&self) -> bool
fn has_history(&self) -> bool
Whether this model has automatic record version history enabled.
When true, the admin panel renders a History affordance on the
detail page and serves /{slug}/{id}/history.
Sourcefn get_history<'a>(
&'a self,
_pool: &'a Pool<AsyncPgConnection>,
_record_id: i64,
_page: u64,
_per_page: u64,
) -> AdminFuture<'a, AdminHistoryPage>
fn get_history<'a>( &'a self, _pool: &'a Pool<AsyncPgConnection>, _record_id: i64, _page: u64, _per_page: u64, ) -> AdminFuture<'a, AdminHistoryPage>
Retrieve a paginated page of version history entries for a record.
The default implementation returns AdminError::Other so models
that do not opt in get a clear error instead of a silent no-op.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".