CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-flask-appbuilder

Simple and rapid application development framework, built on top of Flask, with detailed security, auto CRUD generation, and comprehensive UI components.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

views-crud.mddocs/

Views and CRUD Operations

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.

Capabilities

ModelView Class

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"
)

BaseCRUDView Class

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 dict

SimpleFormView Class

Basic 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"
)

IndexView Class

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)

PublicFormView Class

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)

MasterDetailView Class

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"
)

CompactCRUDMixin

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"
)

MultipleView Class

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

docs

actions-hooks.md

charts.md

cli-tools.md

constants-exceptions.md

core-framework.md

database-models.md

forms-fields.md

index.md

rest-api.md

security.md

views-crud.md

tile.json