More about Flask-AppBuilder

Base views, templates, actions, charts, forms, etc.

CS 374, Fall 2025

IndexView (front page)

  • app.py

    from flask_appbuilder import IndexView
    
    class MyIndexView(IndexView):
        index_template = 'index.jinja'
    
    appbuilder = AppBuilder(indexview=MyIndexView)
    
  • templates/index.jinja

    {% extends "appbuilder/base.html" %}
    {% block content %}
    Add your html/jinja content here...
    {% endblock %}
    

Jinja Templates

Skim the Templates section of FAB docs; scroll down to:
"This main structure of jinja2 on the baselayout template is:"

Name Description Default Route
List Displays a table of records for the model. .../list/
Add Displays a form to create a new record. .../add/
Edit Displays a form to update an existing record. .../edit/<pk>
Show Displays record details in read-only form. .../show/<pk>

Exercise 1: Create Your Index Page

  1. Update app.py
  2. Create index.jinja
  3. Be creative

BaseView (custom page)

Skim the BaseView section of FAB docs

See in profs repo: about.jinja and about.md

from flask_appbuilder import BaseView, expose


class AboutView(BaseView):
    route_base = "/about"

    @expose("/")
    def about(self):
        return self.render_template("about.jinja",
            content=md_to_html("about.md"))


appbuilder.add_view_no_menu(AboutView())

Rendering Markdown

Skim references: Using Markdown and Extensions

from markdown import markdown
from pathlib import Path


def md_to_html(filename: str) -> str:
    """Render a markdown file as html."""
    path = Path("templates") / filename
    text = path.read_text(encoding="utf-8")
    return markdown(text, extensions=["attr_list"])

Exercise 2: Create Your About Page

  1. Update views.py
  2. Create about.jinja
  3. Create about.md (optional)
  4. Be creative

More about Flask

Skim the following sections of the Flask Quickstart:

If time permits:

  • Alerts in Bootstrap 3.4 docs

Flask-AppBuilder Actions

Skim the Actions section of FAB docs

from flask import flash, redirect
from flask_appbuilder.actions import action

Method of a ModelView class:

    @action("myaction", "Send reminder email", "Are you sure?", "fa-email")
    def send_email(self, items):
        # items may be a single College object or a list of College objects
        if not isinstance(items, list):
            items = [items]
        flash(f"{len(items)} emails sent!", "success")
        return redirect(self.get_redirect())

@action Decorator

See flask_appbuilder.actions in API Reference

Possible return values:

  1. Redirect (most common)
    return redirect(self.get_redirect())  # or self.get_url("/list")
    
  2. Render a template
    return self.render_template("example.jinja", item=item)
    
  3. Return JSON (for API-like actions)
    return jsonify(success=True, count=len(items))
    

Exercise 3: Add Your First Action

  1. Update views.py
  2. Be creative

Chart Views

Skim the Chart Views section of FAB docs

  • DirectChartView

    • Aggregation is done in Python (in memory)
    • Typical use: precomputed stats, external sources
  • GroupByChartView

    • Aggregation is done by the database (SQL-level).
    • Typical use: counts, sums, averages by category

DirectByChartView

from flask_appbuilder.charts.views import DirectByChartView

class Volunteer_College_Chart(DirectByChartView):
    datamodel = SQLAInterface(models.Volunteer_College)
    chart_title = "Volunteers by College"
    definitions = [
        {
            "group": "college_code",
            "series": ["students"]
        },
        # can add other groupings
    ]

Automatic input form + Google Charts template!
chart_type can be PieChart, ColumnChart, or LineChart

GroupByChartView

from flask_appbuilder.charts.views import GroupByChartView
from flask_appbuilder.models.group import aggregate_count

class Workshop_Department_Chart(GroupByChartView):
    datamodel = SQLAInterface(models.Workshop_Department)
    chart_title = "Workshop Leaders"
    definitions = [
        {
            "group": "college_code",
            "series": [(aggregate_count, "leader")]
        },
        # can add other groupings
    ]

Can also use aggregate_sum or aggregate_avg (or all three)

Exercise 4: Add Your First Chart

  1. Define a ChartView class for one of your SQL views
  2. Experiment with different definitions
  3. Consider other options for chart_type

Using VS Code's Debugger

Notice .vscode/launch.json in the profs repo

Demo:

  1. How to generate this file from "Run and Debug"
  2. How to edit options using IntelliSense (ctrl+space)

Notes about args:

  • --no-debugger because running within VS Code instead
  • --no-reload because that can get confusing when debugging

Exercise 5: Practice Debugging

  1. Copy launch.json (or create your own)
  2. Set a breakpoint in one of your actions
  3. Start the VS Code debugger (press F5)
  4. Navigate to the action in the browser
  5. Step through your code, inspect variables
  6. Figure out how to restart the flask app

Next Steps

  • Define custom input forms

  • Implement your application logic

    • Time to build the project you originally proposed!