Dashing through Christmas Songs using Dash and SQL | by Cody Glickman, PhD | Towards Data Science

Ladies and Gentleman, Mr. Bing Crosby! tl;dr Find the code for the web application on GitHub.
This article is an overview of my struggles and triumphs using Dash to create a web application on top of a SQL database. The article is broken down into 4 parts: Creating the SQL database, installing the Dash environment, building the web application, running the application. I am new to the Dash environment and am inspired by the flexibility. There are other web application creation engines like Viola that may be worth exploring as well. Dash is refreshing in that includes the unique feature of tabs that can display different objects.
I created a CSV file from the Christmas songs in the United States table on Wikipedia. After some manual formatting, I had a CSV file with 4 columns [Song Name, Artist Name, Year of Release, Other Information]. Pandas is the only library that needs to be installed prior to converting a CSV to a SQL database in the script below. The module sqlite3 is already apart of my python distribution.
import pandas as pdimport sqlite3conn = sqlite3.connect('Songs.db')c = conn.cursor()# Create table with headersc.execute('''CREATE TABLE Songs             ([generated_id] INTEGER PRIMARY KEY,[Song_Name] text,              [Artist_Name] text, [Year] date, [Other] text)''')conn.commit()# Convert CSV to SQLread_songs = pd.read_csv('Chrismas_Songs.csv')read_songs.to_sql('Songs', conn, if_exists='append', index = False)
Briefly, the code creates a SQL table using the execute function with the SQL command inside. The table is populated using Pandas when we export the CSV file into the previously empty SQL table. Now that our SQL database is ready, time for the difficult installation of Dash.
Dash installation tips can be found on the Dash homepage. The packages needed to install for this project included
## Install Plotlypip install plotly## Install Pandaspip install pandas## Install Dash and Componentspip install dashpip install dash-bootstrap-componentspip install dash-html-componentspip install dash-table
Building Structure of the Web Application
index.pyapp.pydatabase/|_ __init__.py|_ Chrismas_Songs.csv|_ Songs.db|_ transforms.pytabs/|_ __init__.py|_ sidepanel.py|_ tab1.py|_ tab2.py
I import data functions from the database/ and tabs/ folders, so I have to include a blank file called __init__.py to let python know this is a module. The web application will run from index.py which calls on every other python file including the app.py.
Building the application starts with the app.py file. Below, we are calling the app and connecting it to a server (in the index file)
app.py
import dashimport dash_bootstrap_components as dbcapp = dash.Dash(__name__, external_stylesheets =[dbc.themes.BOOTSTRAP])server = app.serverapp.config.suppress_callback_exceptions = True
The index file is where the magic happens. This is the quarterback of your web application. Dash uses callbacks to get data from the client (web) and operate on the server (backend). Below is an example from the index file for the complete index file see the GitHub.
index.py
[Not the complete file, download or copy the complete file from the Github]
app.layout = sidepanel.layout@app.callback(Output('tabs-content', 'children'),              [Input('tabs', 'value')])def render_content(tab):    if tab == 'tab-1':        return tab1.layout    elif tab == 'tab-2':        return tab2.layout@app.callback(Output('table-sorting-filtering', 'data'), [Input('table-sorting-filtering', "page_current"), Input('table-sorting-filtering', "page_size"), Input('table-sorting-filtering', 'sort_by'), Input('table-sorting-filtering', 'filter_query'), Input('Last_Decade', 'value'), Input('year-slider', 'value'), Input('Artist-drop', 'value')])# function to filter data table def update_table(page_current, page_size, sort_by, filter, yearcheck, prices, artists):# insert function content hereif __name__ == '__main__':    app.run_server(debug = True)
Let’s break this down from the beginning. The app.layout creates the side bar with the user inputs, more will be explained in the sidepanel.py breakdown. The @app.callback both renders the tabs (Data Table and Histogram) as well as calls the filtering by the user selection. The input in the @app.callback corresponds to the parameters in the functions below. For example, in the first @app.callback, tabs is identical to the tab parameter in the render_content function and Last_Decade is identical to yearcheck in the update_table function. The final piece is the call to the app server in the if __name__ == ‘__main__’ function.
Database/transforms.py
This file connects the SQL database to our index file and web application.
import dashimport dash_bootstrap_components as dbcimport dash_core_components as dccimport dash_html_components as htmlimport pandas as pdimport sqlite3import dashfrom dash.dependencies import Input, Outputimport dash_tableimport pandas as pdconn = sqlite3.connect(r"/Users/stronglab2/Documents/Datadolittle/Dashing_Through/database/Songs.db")c = conn.cursor()df = pd.read_sql("select * from Songs", conn)
Tabs/tab1.py
[Not the complete file, download or copy the complete file from the Github]
Tab1.py creates the data table in the first tab. This file also includes formatting options for the cells.
## Load SQL Database into tabledf = transforms.dfPAGE_SIZE = 50layout = html.Div(dash_table.DataTable(id='table-sorting-filtering',columns=[{'name': i, 'id': i, 'deletable': True} for i in df[['Song_Name','Year', 'Artist_Name','Other']]], ..................
The SQL data is loaded into a pandas data frame and displayed as a dash DataTable. We then create the columns for the DataTable. The dots after defining the columns means there is more details in the full file.
Tabs/tab2.py
[Not the complete file, download or copy the complete file from the Github]
Tab2.py creates the histogram in the second tab. This file also includes @app.callbacks to update based on user selections.
df = transforms.dflayout = html.Div(    id='table-paging-with-graph-container',    className="five columns")@app.callback(Output('table-paging-with-graph-container', "children"),              [Input('Last_Decade', 'value')                  , Input('year-slider', 'value')                  , Input('Artist-drop', 'value')               ])def update_graph(yearcheck, prices, artists):....................................................................    graph_plotly = go.Histogram(x=dff['Year'],                      name="Histotest"                      , opacity=0.7)    return html.Div([dcc.Graph(id='histo-graphic',figure={'data':[graph_plotly], ..........
The histogram is generated with the go.Histogram function and displayed in the tab by html.Dic([dcc.Graph ...
Tabs/sidepanel.py
[Not the complete file, download or copy the complete file from the Github]
The side panel allows the user to interact with the web application. There are three interactions. The last decade checkbox (songs released after 2009), the artist dropdown (more than one artist can be selected), or the date range of release (1910–2020). The table and histogram update according to the selections.
layout = html.Div([    html.H2('Filters')    , dcc.Checklist(id='Last_Decade'                    , options=[            {'label': ' Released this decade ', 'value': 'Y'}        ])        ,html.Div([html.P() ,html.H5('Artist'), dcc.Dropdown(id = 'Artist-drop'                ,options=[                     {'label': i, 'value': i} for i in df['Artist_Name'].unique()],                value=[],                multi=True            )])          ,html.Div([html.H5('Year Slider')                   , dcc.RangeSlider(id='year-slider'...............
This file creates all three interaction options. Each option is separated by html.Div then a call to dash_core_components (dcc) with the type of interaction. The ids are called in the index.py file and the tab2.py to update the table and the histogram.
For those looking to see a working example, install the required packages and download the repository from GitHub. Screenshots below show the web application.
To run the app, simply type python index.py when inside the application directory. You may see a prompt below showing the app is running on your local machine.
Running on http://127.0.0.1:8050/Debugger PIN: 829-054-282* Serving Flask app "app" (lazy loading)* Environment: productionWARNING: Do not use the development server in a production environment.Use a production WSGI server instead.* Debug mode: onRunning on http://127.0.0.1:8050/Debugger PIN: 182-493-929
Simply copy and paste http://127.0.0.1:8050/ into a web browser, the application is started!
There you have it a simple web application built using Dash and SQL. My name is Cody Glickman and I can be found on LinkedIn. Be sure to check out some of my other articles in the realm of data science or web development.