Simple and rapid application development framework, built on top of Flask, with detailed security, auto CRUD generation, and comprehensive UI components.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Model views with automatic CRUD operations, form generation, validation, pagination, searching, and filtering capabilities. The view system provides comprehensive web interfaces for database models with minimal configuration while supporting extensive customization.
Complete CRUD view implementation providing list, show, add, edit, and delete operations with automatic form generation, validation, and security integration.
from flask_appbuilder import ModelView
from flask_appbuilder.models.sqla.interface import SQLAInterface
from flask_appbuilder.baseviews import expose
from flask_appbuilder.security.decorators import has_access
class ModelView(BaseCRUDView):
"""
Complete CRUD view for SQLAlchemy models with automatic
form generation and comprehensive database operations.
"""
@expose('/list/')
@has_access
def list(self):
"""
List view with pagination, search, and filtering.
Returns:
Rendered list template with model data
"""
@expose('/show/<pk>')
@has_access
def show(self, pk):
"""
Show single model instance details.
Parameters:
- pk: Primary key value
Returns:
Rendered show template with model data
"""
@expose('/add/', methods=['GET', 'POST'])
@has_access
def add(self):
"""
Add new model instance with form.
Returns:
GET: Rendered add form template
POST: Redirect after successful creation or form with errors
"""
@expose('/edit/<pk>', methods=['GET', 'POST'])
@has_access
def edit(self, pk):
"""
Edit existing model instance with form.
Parameters:
- pk: Primary key value
Returns:
GET: Rendered edit form template
POST: Redirect after successful update or form with errors
"""
@expose('/delete/<pk>')
@has_access
def delete(self, pk):
"""
Delete model instance by primary key.
Parameters:
- pk: Primary key value
Returns:
Redirect to list view with flash message
"""
@expose('/download/<pk>')
@has_access
def download(self, pk):
"""
Download file associated with model instance.
Parameters:
- pk: Primary key value
Returns:
File download response or 404
"""
@expose('/action/', methods=['POST'])
@has_access
def action_post(self):
"""
Execute bulk actions on selected model instances.
Returns:
Redirect with action results
"""
# Complete ModelView configuration example
class PersonModelView(ModelView):
# Required: data model interface
datamodel = SQLAInterface(Person)
# Column configurations
list_columns = ['name', 'email', 'department', 'active', 'created_on']
show_columns = ['name', 'email', 'phone', 'department', 'active', 'created_on', 'updated_on']
add_columns = ['name', 'email', 'phone', 'department', 'active']
edit_columns = ['name', 'email', 'phone', 'department', 'active']
# Search configuration
search_columns = ['name', 'email']
# Column labels and descriptions
label_columns = {
'name': 'Full Name',
'email': 'Email Address',
'created_on': 'Created Date'
}
description_columns = {
'email': 'Contact email address for notifications',
'active': 'Whether the person is currently active'
}
# Ordering and pagination
order_columns = ['name', 'email', 'created_on']
page_size = 25
# Base filters (always applied)
base_filters = [['active', FilterEqual, True]]
# Form field sets for organization
add_fieldsets = [
('Personal Info', {'fields': ['name', 'email', 'phone']}),
('Organization', {'fields': ['department', 'active']})
]
edit_fieldsets = [
('Personal Info', {'fields': ['name', 'email', 'phone']}),
('Organization', {'fields': ['department', 'active']})
]
# Register view with AppBuilder
appbuilder.add_view(
PersonModelView,
"List Persons",
icon="fa-address-book-o",
category="People"
)Foundation class for CRUD operations providing the core functionality that ModelView extends, with lifecycle hooks and customization points.
from flask_appbuilder.baseviews import BaseCRUDView
class BaseCRUDView(BaseModelView):
"""
Base class for CRUD views providing core database operations
and customization hooks for the CRUD lifecycle.
"""
# Internal CRUD methods (override for customization)
def _list(self, **kwargs):
"""
Internal list view logic.
Parameters:
- **kwargs: Additional context variables
Returns:
Dict with view context data
"""
def _show(self, pk):
"""
Internal show view logic.
Parameters:
- pk: Primary key value
Returns:
Dict with view context data
"""
def _add(self):
"""
Internal add view logic.
Returns:
Dict with view context data or redirect response
"""
def _edit(self, pk):
"""
Internal edit view logic.
Parameters:
- pk: Primary key value
Returns:
Dict with view context data or redirect response
"""
def _delete(self, pk):
"""
Internal delete view logic.
Parameters:
- pk: Primary key value
Returns:
Redirect response with flash message
"""
# Lifecycle hooks
def pre_add(self, item):
"""
Hook called before adding new item to database.
Parameters:
- item: Model instance to be added
"""
def post_add(self, item):
"""
Hook called after successfully adding item.
Parameters:
- item: Added model instance
"""
def pre_update(self, item):
"""
Hook called before updating item in database.
Parameters:
- item: Model instance to be updated
"""
def post_update(self, item):
"""
Hook called after successfully updating item.
Parameters:
- item: Updated model instance
"""
def pre_delete(self, item):
"""
Hook called before deleting item from database.
Parameters:
- item: Model instance to be deleted
"""
def post_delete(self, item):
"""
Hook called after successfully deleting item.
Parameters:
- item: Deleted model instance
"""
def prefill_form(self, form, pk):
"""
Pre-fill edit form with additional data.
Parameters:
- form: WTForms form instance
- pk: Primary key of item being edited
"""
def process_form(self, form, is_created):
"""
Process form data before database operation.
Parameters:
- form: WTForms form instance with submitted data
- is_created: Boolean indicating if this is create (True) or update (False)
Returns:
Model instance with processed data
"""
# CRUD View configuration properties
datamodel = None # SQLAlchemy interface (required)
# View titles
list_title = "List" # List view title
show_title = "Show Record" # Show view title
add_title = "Add Record" # Add form title
edit_title = "Edit Record" # Edit form title
# Column configurations
list_columns = [] # Columns shown in list view
show_columns = [] # Columns shown in show view
add_columns = [] # Columns in add form
edit_columns = [] # Columns in edit form
show_exclude_columns = [] # Columns excluded from show
add_exclude_columns = [] # Columns excluded from add form
edit_exclude_columns = [] # Columns excluded from edit form
order_columns = [] # Columns available for sorting
# Pagination and display
page_size = 20 # Default page size
show_template = "appbuilder/general/model/show.html"
list_template = "appbuilder/general/model/list.html"
add_template = "appbuilder/general/model/add.html"
edit_template = "appbuilder/general/model/edit.html"
# Widget classes
list_widget = None # List widget class
show_widget = None # Show widget class
add_widget = None # Add form widget class
edit_widget = None # Edit form widget class
# Form configurations
show_fieldsets = [] # Field groupings for show view
add_fieldsets = [] # Field groupings for add form
edit_fieldsets = [] # Field groupings for edit form
description_columns = {} # Column descriptions
validators_columns = {} # Column validators
formatters_columns = {} # Column formatters
add_form_extra_fields = {} # Extra fields for add form
edit_form_extra_fields = {} # Extra fields for edit form
add_form_query_rel_fields = {} # Related field queries for add
edit_form_query_rel_fields = {} # Related field queries for edit
# Forms (auto-generated)
add_form = None # Add form instance
edit_form = None # Edit form instance
# Related views and actions
related_views = [] # Related ModelView classes
actions = {} # Available actions dictBasic form view for simple form processing without database model integration, useful for contact forms, settings, and other non-CRUD operations.
from flask_appbuilder import SimpleFormView
from wtforms import Form, StringField, validators
from wtforms.validators import DataRequired
class SimpleFormView(BaseFormView):
"""Simple form handling without model integration."""
@expose('/', methods=['GET', 'POST'])
def this_form_get(self):
"""Handle GET request - display form."""
@expose('/form', methods=['POST'])
def this_form_post(self):
"""Handle POST request - process form."""
# Example: Contact form
class ContactForm(Form):
name = StringField('Name', [DataRequired()])
email = StringField('Email', [DataRequired(), validators.Email()])
message = StringField('Message', [DataRequired()])
class ContactFormView(SimpleFormView):
form = ContactForm
form_title = "Contact Us"
def form_post(self, form):
# Process the form submission
if form.validate():
name = form.name.data
email = form.email.data
message = form.message.data
# Send email, save to database, etc.
send_contact_email(name, email, message)
flash("Thank you for your message!", "success")
return redirect(url_for('ContactFormView.this_form_get'))
# Form validation failed - return form with errors
return self.render_template(
self.form_template,
form=form,
form_title=self.form_title
)
# Register form view
appbuilder.add_view(
ContactFormView,
"Contact",
icon="fa-envelope"
)Default index/home page view providing the application landing page and navigation entry point.
from flask_appbuilder import IndexView
class IndexView(BaseView):
"""Default index page view for Flask-AppBuilder applications."""
route_base = "" # Root route
default_view = "index" # Default method
index_template = "appbuilder/index.html" # Index template
@expose('/')
def index(self):
"""
Index page endpoint.
Returns:
Rendered index template
"""
# Custom index view example
class CustomIndexView(IndexView):
index_template = "my_index.html"
@expose('/')
def index(self):
# Get dashboard data
user_count = db.session.query(User).count()
recent_activity = get_recent_activity()
return self.render_template(
self.index_template,
user_count=user_count,
recent_activity=recent_activity
)
# Use custom index view
appbuilder = AppBuilder(app, db.session, indexview=CustomIndexView)Form view accessible without authentication, useful for registration forms, public contact forms, and other publicly accessible functionality.
from flask_appbuilder import PublicFormView
class PublicFormView(SimpleFormView):
"""Form view accessible without authentication."""
# No @has_access decorator - publicly accessible
# Inherits form processing from SimpleFormView
# Example: Public registration form
class RegistrationForm(Form):
username = StringField('Username', [DataRequired()])
email = StringField('Email', [DataRequired(), validators.Email()])
password = PasswordField('Password', [DataRequired()])
class PublicRegistrationView(PublicFormView):
form = RegistrationForm
form_title = "Register"
def form_post(self, form):
if form.validate():
username = form.username.data
email = form.email.data
password = form.password.data
# Create user account
user = User(username=username, email=email)
user.password = generate_password_hash(password)
db.session.add(user)
db.session.commit()
flash("Registration successful!", "success")
return redirect(url_for('AuthDBView.login'))
return self.render_template(
self.form_template,
form=form,
form_title=self.form_title
)
# Register public view (no authentication required)
appbuilder.add_view_no_menu(PublicRegistrationView)Master-detail view pattern for displaying related models in a hierarchical interface, showing a master record with its related detail records.
from flask_appbuilder import MasterDetailView
class MasterDetailView(BaseView):
"""Master-detail view pattern for related models."""
# Master model configuration
datamodel = None # Master model interface
# Detail models configuration
related_views = [] # List of detail view classes
# Example: Order with Order Items
class OrderMasterDetailView(MasterDetailView):
datamodel = SQLAInterface(Order)
related_views = [OrderItemModelView]
list_columns = ['order_number', 'customer', 'total', 'order_date']
show_columns = ['order_number', 'customer', 'total', 'order_date', 'status']
class OrderItemModelView(ModelView):
datamodel = SQLAInterface(OrderItem)
list_columns = ['product', 'quantity', 'price', 'subtotal']
# Register master-detail view
appbuilder.add_view(
OrderMasterDetailView,
"Orders",
icon="fa-shopping-cart",
category="Sales"
)Mixin providing compact CRUD operations with streamlined interface for simple models requiring minimal configuration.
from flask_appbuilder import CompactCRUDMixin, ModelView
class CompactCRUDMixin:
"""Mixin for compact CRUD operations with simplified interface."""
# Example: Simple model with compact interface
class TagModelView(CompactCRUDMixin, ModelView):
datamodel = SQLAInterface(Tag)
list_columns = ['name', 'color']
add_columns = ['name', 'color']
edit_columns = ['name', 'color']
# Compact interface reduces UI complexity
page_size = 10
show_fieldsets = [
('Tag Info', {'fields': ['name', 'color'], 'expanded': True})
]
appbuilder.add_view(
TagModelView,
"Tags",
icon="fa-tag",
category="Admin"
)Container view for organizing multiple related views in a single interface, useful for creating dashboard-style pages or grouped functionality.
from flask_appbuilder import MultipleView
class MultipleView(BaseView):
"""Multiple views in single interface."""
views = [] # List of view instances
# Example: Admin dashboard with multiple views
class AdminDashboardView(MultipleView):
views = [
{'view': UserStatsView(), 'size': 6}, # Half width
{'view': SystemHealthView(), 'size': 6}, # Half width
{'view': RecentActivityView(), 'size': 12} # Full width
]
appbuilder.add_view(
AdminDashboardView,
"Admin Dashboard",
icon="fa-dashboard",
category="Admin"
)Install with Tessl CLI
npx tessl i tessl/pypi-flask-appbuilder