Simple and extensible admin interface framework for Flask
86
Quality
Pending
Does it follow best practices?
Impact
86%
1.30xAverage score across 10 eval scenarios
Base model view functionality for creating database-driven administrative interfaces with comprehensive CRUD operations, filtering, searching, and batch actions.
Foundation class for model-based admin views providing list, create, edit, and delete operations with extensive customization options.
class BaseModelView(BaseView, ActionsMixin):
"""
Base class for model-based admin views.
"""
# List view configuration
list_columns = None # Columns to display in list view
column_exclude_list = None # Columns to exclude from list
column_auto_select_related = True # Auto-select related models
column_select_related_list = None # Explicitly select related models
column_display_pk = False # Display primary key column
column_hide_backrefs = True # Hide back-references
# Column formatting and display
column_formatters = {} # Custom column formatters
column_formatters_export = {} # Export-specific formatters
column_type_formatters = {} # Type-based formatters
column_labels = {} # Custom column labels
column_descriptions = {} # Column descriptions/tooltips
column_sortable_list = None # Sortable columns
column_default_sort = None # Default sort column and direction
# Filtering and searching
column_filters = None # Available filters
named_filter_urls = False # Use named filter URLs
column_searchable_list = None # Searchable columns
# List view behavior
page_size = 20 # Items per page
can_set_page_size = False # Allow user to change page size
# CRUD permissions
can_create = True # Allow creating new records
can_edit = True # Allow editing records
can_delete = True # Allow deleting records
can_view_details = False # Allow viewing record details
# Export functionality
can_export = False # Allow data export
export_max_rows = 0 # Maximum export rows (0 = unlimited)
export_types = ['csv'] # Supported export formats
# Form configuration
form_columns = None # Columns in create/edit forms
form_excluded_columns = None # Columns excluded from forms
form_include_pk = False # Include primary key in forms
form_overrides = {} # Custom field overrides
form_widget_args = {} # Widget arguments
form_extra_fields = {} # Additional form fields
# Form validation and processing
form_edit_rules = None # Edit form rules
form_create_rules = None # Create form rules
form_args = {} # Form field arguments
# Details view
details_modal = False # Show details in modal
details_modal_template = None # Details modal template
# Templates
list_template = 'admin/model/list.html'
edit_template = 'admin/model/edit.html'
create_template = 'admin/model/create.html'
details_template = 'admin/model/details.html'
def __init__(
self,
model=None,
name=None,
category=None,
endpoint=None,
url=None,
static_folder=None,
menu_class_name=None,
menu_icon_type=None,
menu_icon_value=None
):
"""
Initialize base model view.
Args:
model: Model class
name (str, optional): View name for menu
category (str, optional): Menu category
endpoint (str, optional): Blueprint endpoint
url (str, optional): URL prefix
static_folder (str, optional): Static files folder
menu_class_name (str, optional): Menu CSS class
menu_icon_type (str, optional): Icon type
menu_icon_value (str, optional): Icon identifier
"""
# Model operations (abstract methods to be implemented by ORM-specific views)
def get_pk_value(self, model):
"""
Get primary key value from model instance.
Args:
model: Model instance
Returns:
Primary key value
"""
def get_list(self, page, sort_column, sort_desc, search, filters, execute=True, page_size=None):
"""
Get model list with pagination, sorting, and filtering.
Args:
page (int): Page number (0-based)
sort_column (str): Sort column name
sort_desc (bool): Sort descending
search (str): Search query
filters (list): Active filters
execute (bool): Execute query immediately
page_size (int, optional): Items per page
Returns:
tuple: (count, data) or query object if execute=False
"""
def get_one(self, id):
"""
Get single model instance by ID.
Args:
id: Primary key value
Returns:
Model instance or None
"""
def create_model(self, form):
"""
Create new model instance from form data.
Args:
form: Form instance with data
Returns:
bool: True if successful
"""
def update_model(self, form, model):
"""
Update model instance from form data.
Args:
form: Form instance with data
model: Model instance to update
Returns:
bool: True if successful
"""
def delete_model(self, model):
"""
Delete model instance.
Args:
model: Model instance to delete
Returns:
bool: True if successful
"""
# Form methods
def scaffold_form(self):
"""
Create form class from model.
Returns:
Form class
"""
def scaffold_list_form(self, widget=None, validators=None):
"""
Create list form for inline editing.
Args:
widget: Form widget
validators: Field validators
Returns:
Form class
"""
def scaffold_filters(self, name):
"""
Create filters for column.
Args:
name (str): Column name
Returns:
list: Filter instances
"""
# View methods (exposed via @expose decorator)
def index_view(self):
"""
List view displaying paginated model data.
Returns:
str: Rendered template
"""
def create_view(self):
"""
Create new model instance view.
Returns:
str: Rendered template or redirect
"""
def edit_view(self):
"""
Edit existing model instance view.
Returns:
str: Rendered template or redirect
"""
def delete_view(self):
"""
Delete model instance view.
Returns:
Redirect response
"""
def details_view(self):
"""
View model instance details.
Returns:
str: Rendered template
"""
def export(self, export_type):
"""
Export model data.
Args:
export_type (str): Export format ('csv', etc.)
Returns:
Export response
"""Configuration classes for managing list view state and filter groups.
class ViewArgs:
def __init__(
self,
page=None,
page_size=None,
sort=None,
sort_desc=None,
search=None,
filters=None,
extra_args=None
):
"""
Initialize list view arguments.
Args:
page (int, optional): Page number
page_size (int, optional): Items per page
sort (str, optional): Sort column
sort_desc (bool, optional): Sort descending
search (str, optional): Search query
filters (list, optional): Active filters
extra_args (dict, optional): Additional arguments
"""
def clone(self, **kwargs):
"""
Clone arguments with modifications.
Args:
**kwargs: Arguments to override
Returns:
ViewArgs: Cloned instance
"""
class FilterGroup:
def __init__(self, label):
"""
Initialize filter group.
Args:
label (str): Group label
"""
def append(self, filter):
"""
Add filter to group.
Args:
filter: Filter instance
"""
def non_lazy(self):
"""
Get non-lazy filter representation.
Returns:
FilterGroup: Non-lazy group
"""Batch action system for performing operations on multiple selected items.
def action(name, text, confirmation=None):
"""
Decorator to expose batch actions on selected items.
Args:
name (str): Action identifier
text (str): Action display text
confirmation (str, optional): Confirmation message
Returns:
function: Decorated method
"""
class ActionsMixin:
"""
Mixin providing batch action functionality to views.
"""
def __init__(self):
"""
Initialize actions mixin.
"""
def init_actions(self):
"""
Scan and initialize action methods.
"""
def is_action_allowed(self, name):
"""
Check if action is permitted for current user.
Args:
name (str): Action name
Returns:
bool: True if allowed
"""
def get_actions_list(self):
"""
Get list of allowed actions for current user.
Returns:
list: Available actions
"""
def handle_action(self, return_view=None):
"""
Process action requests from list view.
Args:
return_view (str, optional): View to return to after action
Returns:
Response: Flask response
"""from flask_admin.contrib.sqla import ModelView
from flask_admin.actions import action
from flask import flash, redirect, url_for
class UserModelView(ModelView):
# List view configuration
list_columns = ['id', 'name', 'email', 'created_at', 'is_active']
column_searchable_list = ['name', 'email']
column_filters = ['is_active', 'created_at']
column_labels = {'is_active': 'Active Status'}
# Form configuration
form_columns = ['name', 'email', 'is_active', 'role']
form_widget_args = {
'email': {'placeholder': 'user@example.com'}
}
# Permissions
can_create = True
can_edit = True
can_delete = False
can_export = True
# Custom action
@action('activate', 'Activate Users', 'Are you sure you want to activate selected users?')
def action_activate(self, ids):
try:
query = User.query.filter(User.id.in_(ids))
count = query.update({User.is_active: True}, synchronize_session=False)
db.session.commit()
flash(f'Successfully activated {count} users.', 'success')
except Exception as ex:
flash(f'Failed to activate users: {str(ex)}', 'error')
# Override permissions
def is_accessible(self):
return current_user.is_authenticated and current_user.is_admin
def inaccessible_callback(self, name, **kwargs):
return redirect(url_for('security.login', next=request.url))
# Register with admin
admin.add_view(UserModelView(User, db.session, name='Users', category='Management'))from markupsafe import Markup
class ProductModelView(ModelView):
column_formatters = {
'price': lambda v, c, m, p: f'${m.price:.2f}',
'image': lambda v, c, m, p: Markup(f'<img src="{m.image_url}" width="50">') if m.image_url else '',
'status': lambda v, c, m, p: Markup(f'<span class="label label-{m.status_color}">{m.status}</span>')
}
column_formatters_export = {
'price': lambda v, c, m, p: m.price, # Export raw price value
'image': lambda v, c, m, p: m.image_url or '' # Export URL only
}Install with Tessl CLI
npx tessl i tessl/pypi-flask-admindocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10