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
Data visualization with chart views supporting pie charts, bar charts, line charts, and custom aggregation functions. The chart system provides comprehensive data visualization capabilities with Google Charts integration and flexible data aggregation.
Foundation class for all chart views providing core charting functionality, data processing, and rendering capabilities with Google Charts integration.
from flask_appbuilder.charts.views import BaseChartView
from flask_appbuilder.models.sqla.interface import SQLAInterface
class BaseChartView(BaseModelView):
"""
Base class for chart views providing core charting functionality.
"""
def __init__(self):
"""Initialize chart view with default configurations."""
def chart(self):
"""
Main chart rendering method.
Returns:
Rendered chart template with data and configuration
"""
# Chart configuration properties
chart_template = "appbuilder/general/charts/chart.html" # Chart template
chart_widget = None # Chart widget class
chart_title = "Chart" # Chart title
chart_type = "PieChart" # Google Charts type
chart_3d = False # Enable 3D rendering
width = 400 # Chart width in pixels
height = 300 # Chart height in pixels
# Data configuration
group_bys = [] # Grouping columns list
search_columns = [] # Searchable columns
label_columns = {} # Column labels
# Chart types available:
# - PieChart: Pie chart visualization
# - ColumnChart: Vertical bar chart
# - BarChart: Horizontal bar chart
# - LineChart: Line graph
# - AreaChart: Area chart
# - ScatterChart: Scatter plot
# - ComboChart: Combination chart
# - Gauge: Gauge visualization
# - GeoChart: Geographic chart
# Usage example
class SalesChartView(BaseChartView):
datamodel = SQLAInterface(Sale)
chart_title = "Sales Analysis"
chart_type = "ColumnChart"
width = 600
height = 400
# Define grouping and aggregation
group_bys = ['product_category']
search_columns = ['sale_date', 'product_category']
# Column labels for display
label_columns = {
'product_category': 'Product Category',
'total_amount': 'Total Sales'
}
# Register chart view
appbuilder.add_view(
SalesChartView,
"Sales Chart",
icon="fa-bar-chart",
category="Analytics"
)Direct data chart view for simple charts that display data directly without complex grouping or aggregation operations.
from flask_appbuilder.charts.views import DirectByChartView
class DirectByChartView(BaseChartView):
"""
Direct chart view for simple data visualization without grouping.
Displays raw data directly in chart format.
"""
# Simple chart example - Monthly sales trend
class MonthlySalesChart(DirectByChartView):
datamodel = SQLAInterface(MonthlySale)
chart_title = "Monthly Sales Trend"
chart_type = "LineChart"
width = 800
height = 400
# Direct data mapping
search_columns = ['month', 'year']
label_columns = {
'month': 'Month',
'sales_total': 'Sales Amount'
}
# Product inventory levels
class InventoryChart(DirectByChartView):
datamodel = SQLAInterface(Product)
chart_title = "Current Inventory Levels"
chart_type = "BarChart"
# Show product inventory as horizontal bars
search_columns = ['name', 'category']
label_columns = {
'name': 'Product Name',
'stock_quantity': 'Stock Level'
}
# Base filter for active products only
base_filters = [['active', FilterEqual, True]]
# Geographic sales distribution
class SalesGeoChart(DirectByChartView):
datamodel = SQLAInterface(RegionalSale)
chart_title = "Sales by Region"
chart_type = "GeoChart"
width = 700
height = 500
label_columns = {
'country_code': 'Country',
'total_sales': 'Sales Volume'
}Group by chart view for aggregated data visualization supporting complex grouping operations and multiple aggregation functions.
from flask_appbuilder.charts.views import GroupByChartView
from flask_appbuilder.models.group import aggregate_count, aggregate_sum, aggregate_avg
class GroupByChartView(BaseChartView):
"""
Chart view with grouping and aggregation capabilities.
Supports complex data analysis with multiple group-by operations.
"""
# Sales by department with aggregation
class DepartmentSalesChart(GroupByChartView):
datamodel = SQLAInterface(Sale)
chart_title = "Sales by Department"
chart_type = "PieChart"
chart_3d = True
# Group by department and sum sales amounts
group_bys = ['department.name']
# Search and filter options
search_columns = ['department.name', 'sale_date']
base_filters = [
['sale_date', FilterGreater, datetime.date(2023, 1, 1)]
]
label_columns = {
'department.name': 'Department',
'amount': 'Total Sales'
}
# Employee performance by month
class EmployeePerformanceChart(GroupByChartView):
datamodel = SQLAInterface(Sale)
chart_title = "Employee Performance by Month"
chart_type = "ColumnChart"
width = 900
height = 500
# Group by employee and month
group_bys = ['employee.name', 'MONTH(sale_date)']
search_columns = ['employee.name', 'sale_date']
label_columns = {
'employee.name': 'Employee',
'sale_date': 'Month',
'commission': 'Total Commission'
}
# Product sales with multiple metrics
class ProductAnalyticsChart(GroupByChartView):
datamodel = SQLAInterface(Sale)
chart_title = "Product Sales Analytics"
chart_type = "ComboChart"
# Group by product category
group_bys = ['product.category']
# Multiple aggregations: count, sum, average
definitions = [
{
'group': 'product.category',
'series': [
('COUNT(*)', 'Number of Sales'),
('SUM(amount)', 'Total Revenue'),
('AVG(amount)', 'Average Sale Value')
]
}
]
label_columns = {
'product.category': 'Category'
}
# Time-based trend analysis
class SalesTrendChart(GroupByChartView):
datamodel = SQLAInterface(Sale)
chart_title = "Sales Trend Analysis"
chart_type = "LineChart"
width = 1000
height = 400
# Group by date periods
group_bys = ['YEAR(sale_date)', 'MONTH(sale_date)']
search_columns = ['sale_date']
label_columns = {
'sale_date': 'Date',
'amount': 'Sales Amount'
}Widget classes for rendering different chart types with customizable templates and Google Charts integration.
from flask_appbuilder.charts.widgets import ChartWidget, DirectChartWidget
class ChartWidget(RenderTemplateWidget):
"""Base chart widget for rendering Google Charts."""
template = "appbuilder/general/charts/chart.html"
def __call__(self, chart_data, chart_title="", chart_type="PieChart",
width=400, height=300, chart_3d=False, **kwargs):
"""
Render chart widget.
Parameters:
- chart_data: Chart data in Google Charts format
- chart_title: Chart title
- chart_type: Google Charts type
- width: Chart width in pixels
- height: Chart height in pixels
- chart_3d: Enable 3D rendering
- **kwargs: Additional chart options
Returns:
Rendered chart HTML with Google Charts JavaScript
"""
class DirectChartWidget(ChartWidget):
"""Widget for direct data charts without aggregation."""
template = "appbuilder/general/charts/direct_chart.html"
# Custom chart widget example
class CustomChartWidget(ChartWidget):
template = "my_custom_chart.html"
def __call__(self, **kwargs):
# Add custom chart options
kwargs.update({
'backgroundColor': '#f8f9fa',
'titleTextStyle': {'color': '#495057', 'fontSize': 18},
'legend': {'position': 'bottom', 'textStyle': {'fontSize': 12}}
})
return super(CustomChartWidget, self).__call__(**kwargs)
# Usage in chart views
class StyledSalesChart(GroupByChartView):
datamodel = SQLAInterface(Sale)
chart_widget = CustomChartWidget
chart_title = "Styled Sales Analysis"
chart_type = "ColumnChart"
# Advanced chart configuration
class AdvancedChart(GroupByChartView):
datamodel = SQLAInterface(Sale)
chart_title = "Advanced Sales Chart"
chart_type = "ComboChart"
# Custom chart options passed to Google Charts
chart_options = {
'vAxis': {'title': 'Sales Amount'},
'hAxis': {'title': 'Time Period'},
'series': {
0: {'type': 'columns', 'targetAxisIndex': 0},
1: {'type': 'line', 'targetAxisIndex': 1}
},
'vAxes': {
0: {'title': 'Revenue', 'format': 'currency'},
1: {'title': 'Count', 'format': 'decimal'}
}
}Built-in and custom aggregation functions for data processing in chart views with support for mathematical operations and statistical calculations.
from flask_appbuilder.models.group import aggregate_count, aggregate_sum, \
aggregate_avg, aggregate
# Built-in aggregation functions
@aggregate(label="Count")
def aggregate_count(items, col):
"""
Count aggregation function.
Parameters:
- items: List of model instances
- col: Column name (unused for count)
Returns:
Integer count of items
"""
return len(items)
@aggregate(label="Sum")
def aggregate_sum(items, col):
"""
Sum aggregation function.
Parameters:
- items: List of model instances
- col: Column name to sum
Returns:
Sum of column values
"""
return sum(getattr(item, col, 0) or 0 for item in items)
@aggregate(label="Average")
def aggregate_avg(items, col):
"""
Average aggregation function.
Parameters:
- items: List of model instances
- col: Column name to average
Returns:
Average of column values
"""
values = [getattr(item, col, 0) or 0 for item in items]
return sum(values) / len(values) if values else 0
# Custom aggregation functions
@aggregate(label="Maximum")
def aggregate_max(items, col):
"""Maximum value aggregation."""
values = [getattr(item, col, 0) or 0 for item in items]
return max(values) if values else 0
@aggregate(label="Minimum")
def aggregate_min(items, col):
"""Minimum value aggregation."""
values = [getattr(item, col, 0) or 0 for item in items]
return min(values) if values else 0
@aggregate(label="Standard Deviation")
def aggregate_stddev(items, col):
"""Standard deviation aggregation."""
import statistics
values = [getattr(item, col, 0) or 0 for item in items]
return statistics.stdev(values) if len(values) > 1 else 0
@aggregate(label="Median")
def aggregate_median(items, col):
"""Median value aggregation."""
import statistics
values = [getattr(item, col, 0) or 0 for item in items]
return statistics.median(values) if values else 0
# Complex business aggregation
@aggregate(label="Profit Margin")
def aggregate_profit_margin(items, col):
"""Calculate profit margin percentage."""
total_revenue = sum(getattr(item, 'revenue', 0) or 0 for item in items)
total_cost = sum(getattr(item, 'cost', 0) or 0 for item in items)
if total_revenue > 0:
return ((total_revenue - total_cost) / total_revenue) * 100
return 0
# Usage in chart views
class ProfitAnalysisChart(GroupByChartView):
datamodel = SQLAInterface(Sale)
chart_title = "Profit Analysis by Product"
chart_type = "ColumnChart"
# Use custom aggregation
group_bys = ['product.name']
# Define aggregation in chart configuration
definitions = [
{
'group': 'product.name',
'series': [
('aggregate_sum', 'Total Revenue'),
('aggregate_profit_margin', 'Profit Margin %')
]
}
]
# Time-based aggregation
@aggregate(label="Monthly Growth Rate")
def aggregate_growth_rate(items, col):
"""Calculate month-over-month growth rate."""
# Sort items by date
sorted_items = sorted(items, key=lambda x: getattr(x, 'date'))
if len(sorted_items) < 2:
return 0
current_value = getattr(sorted_items[-1], col, 0) or 0
previous_value = getattr(sorted_items[-2], col, 0) or 0
if previous_value > 0:
return ((current_value - previous_value) / previous_value) * 100
return 0
# Weighted average aggregation
@aggregate(label="Weighted Average")
def aggregate_weighted_avg(items, col, weight_col='quantity'):
"""Calculate weighted average."""
total_weight = sum(getattr(item, weight_col, 0) or 0 for item in items)
if total_weight > 0:
weighted_sum = sum(
(getattr(item, col, 0) or 0) * (getattr(item, weight_col, 0) or 0)
for item in items
)
return weighted_sum / total_weight
return 0Advanced data processing capabilities for chart views including filtering, transformation, and custom data preparation.
# Custom data processing in chart views
class CustomDataChart(GroupByChartView):
datamodel = SQLAInterface(Sale)
chart_title = "Custom Data Processing"
def get_group_by_data(self, group_bys, **kwargs):
"""
Override data processing for custom logic.
Parameters:
- group_bys: List of grouping columns
- **kwargs: Additional parameters
Returns:
Processed chart data
"""
# Get base data
data = super(CustomDataChart, self).get_group_by_data(group_bys, **kwargs)
# Apply custom transformations
transformed_data = []
for row in data:
# Custom business logic
transformed_row = self.transform_data_row(row)
transformed_data.append(transformed_row)
return transformed_data
def transform_data_row(self, row):
"""Apply custom transformations to data row."""
# Example: Convert currency, apply business rules, etc.
if 'amount' in row:
row['amount'] = self.format_currency(row['amount'])
return row
def format_currency(self, amount):
"""Format amount as currency."""
return f"${amount:,.2f}"
# Multi-series chart with custom data
class MultiSeriesChart(GroupByChartView):
datamodel = SQLAInterface(Sale)
chart_title = "Multi-Series Analysis"
chart_type = "LineChart"
def get_chart_data(self, group_by, **kwargs):
"""Generate multi-series chart data."""
# Get data for each series
series_data = {}
# Revenue series
revenue_data = self.get_series_data('revenue', group_by, **kwargs)
series_data['Revenue'] = revenue_data
# Profit series
profit_data = self.get_series_data('profit', group_by, **kwargs)
series_data['Profit'] = profit_data
# Format for Google Charts
return self.format_multi_series_data(series_data)
def get_series_data(self, metric, group_by, **kwargs):
"""Get data for specific metric series."""
# Custom query for metric
query = self.datamodel.get_query()
# Apply filters and aggregation
return query.all()
def format_multi_series_data(self, series_data):
"""Format data for multi-series chart."""
# Convert to Google Charts format
formatted_data = []
# Implementation details...
return formatted_data
# Real-time chart with data refresh
class RealTimeChart(GroupByChartView):
datamodel = SQLAInterface(Sale)
chart_title = "Real-Time Sales"
# Auto-refresh configuration
refresh_interval = 30 # seconds
def get_live_data(self):
"""Get live data for real-time updates."""
# Query recent data
cutoff_time = datetime.datetime.now() - datetime.timedelta(hours=1)
query = self.datamodel.get_query().filter(
Sale.created_on >= cutoff_time
)
return query.all()
@expose('/live-data/')
def live_data_endpoint(self):
"""AJAX endpoint for live data updates."""
data = self.get_live_data()
processed_data = self.process_live_data(data)
return jsonify({
'success': True,
'data': processed_data,
'timestamp': datetime.datetime.now().isoformat()
})
# Chart with drill-down capability
class DrillDownChart(GroupByChartView):
datamodel = SQLAInterface(Sale)
chart_title = "Sales with Drill-Down"
@expose('/drill-down/<category>/')
def drill_down(self, category):
"""Drill-down to detailed view for specific category."""
# Get detailed data for category
detailed_data = self.get_category_details(category)
# Render detailed chart
return self.render_template(
'detailed_chart.html',
category=category,
data=detailed_data
)
def get_category_details(self, category):
"""Get detailed breakdown for category."""
query = self.datamodel.get_query().filter(
Sale.category == category
)
return query.all()Install with Tessl CLI
npx tessl i tessl/pypi-flask-appbuilder