Dashboard Project — Plotly Dash Basics
dcc.Graph, wire up a dropdown with @app.callback, and run it locally.
What Is Dash?
Dash is an open-source Python framework, maintained by Plotly, for building interactive web applications — most commonly dashboards — entirely in Python. Under the hood, it runs on Flask (a Python web server) for the backend and React for the frontend, but you never touch either directly: you describe the page's layout and behavior in Python, and Dash generates the HTML/CSS/JS for you.
pip install dash installs it (and pulls in Plotly as a dependency automatically). It's a good idea to also have pandas installed, since dashboards are almost always built on top of a DataFrame.A Minimal Dash App Skeleton
Every Dash app follows the same three-part shape: create an app object, describe app.layout (what's on the page), and run it. Here's the smallest possible working app — no chart yet, just text.
from dash import Dash, dcc, html app = Dash(__name__) app.layout = html.Div([ html.H1("Sales Dashboard"), html.P("A minimal Dash app skeleton."), ]) if __name__ == "__main__": app.run_server(debug=True)
dash.html module provides a Python class for every HTML tag — html.Div, html.H1, html.P, and so on. app.layout is built by nesting these objects, which Dash then renders into actual HTML in the browser. No .html file to write by hand.app.run_server(debug=True), the method used across most existing Dash tutorials and still fully supported. Recent Dash versions (2.11+) also offer app.run(debug=True) as the newer, preferred name for the same thing — both start the same local development server, so either works.Adding a Chart with dcc.Graph
dash.dcc ("Dash Core Components") provides the interactive building blocks — graphs, dropdowns, sliders, date pickers. dcc.Graph(figure=fig) drops any Plotly figure — built with plotly.express, exactly like in the last lesson — straight into the page.
from dash import Dash, dcc, html import plotly.express as px import pandas as pd df = pd.DataFrame({ "city": ["Lahore", "Karachi", "Islamabad", "Faisalabad"], "sales": [820000, 950000, 610000, 430000], }) app = Dash(__name__) fig = px.bar(df, x="city", y="sales", title="Sales by City") app.layout = html.Div([ html.H1("Sales Dashboard"), dcc.Graph(figure=fig), ]) if __name__ == "__main__": app.run_server(debug=True)
fig is a regular Plotly figure, it keeps every bit of interactivity from the last lesson — hover tooltips, zoom, pan — now embedded inside a real web page instead of a standalone HTML file.Making It Interactive with @app.callback
A static chart on a dashboard is only marginally more useful than a static chart anywhere else. Dash's real power is the callback — a Python function that automatically re-runs and updates part of the page whenever an input control changes, wired up with the @app.callback decorator.
from dash import Dash, dcc, html, Input, Output import plotly.express as px import pandas as pd df = pd.DataFrame({ "city": ["Lahore", "Lahore", "Karachi", "Karachi", "Islamabad", "Islamabad"], "month": ["Jan", "Feb", "Jan", "Feb", "Jan", "Feb"], "sales": [420000, 460000, 500000, 530000, 300000, 320000], }) app = Dash(__name__) app.layout = html.Div([ html.H1("City Sales Explorer"), dcc.Dropdown( id="city-dropdown", options=[{"label": c, "value": c} for c in df["city"].unique()], value="Lahore", ), dcc.Graph(id="sales-chart"), ]) @app.callback( Output("sales-chart", "figure"), Input("city-dropdown", "value"), ) def update_chart(selected_city): filtered = df[df["city"] == selected_city] fig = px.bar(filtered, x="month", y="sales", title=f"Sales in {selected_city}") return fig if __name__ == "__main__": app.run_server(debug=True)
Output("sales-chart", "figure") says "this function's return value becomes the figure property of the component with id="sales-chart"" — that's the dcc.Graph above. Input("city-dropdown", "value") says "run this function every time the value property of the component with id="city-dropdown" changes" — that's the dropdown. The decorated function's parameter (selected_city) receives that new value automatically, in the same order as the Inputs are listed."city-dropdown" and "sales-chart" inside Output()/Input() must exactly match the id= given to the actual component in app.layout. A typo here is one of the most common Dash beginner errors — the app runs, but the callback silently never fires because it's pointed at an id that doesn't exist.Running the App Locally
Save any of the scripts above as app.py and run it like any other Python file:
python app.py
Dash starts a local development server and prints a URL — by default http://127.0.0.1:8050/. Open that address in a browser to see the dashboard, and it stays running (and reloading on save, thanks to debug=True) until you stop the script.
Lesson Summary
Let's recap everything you learned in this lesson:
Output("sales-chart", "figure"), what do the two arguments refer to?Extend the interactive app from Section 4 with a second control.
Starting from the interactive app in Section 4, add a second
dcc.Dropdown (id "chart-type-dropdown") that lets the user switch the chart between "bar" and "line". Update the @app.callback to take two Inputs — the city and the chart type — and build either px.bar() or px.line() inside update_chart() depending on which is selected.
Rules: The callback function needs one parameter per
Input, in the same order they're listed inside @app.callback(...).
💡 Show hints if you're stuck
- Second dropdown:
dcc.Dropdown(id="chart-type-dropdown", options=["bar", "line"], value="bar") - Callback signature:
@app.callback(Output("sales-chart", "figure"), Input("city-dropdown", "value"), Input("chart-type-dropdown", "value")) - Function:
def update_chart(selected_city, chart_type):then branch withif chart_type == "bar": ... else: ...