Welcome! In this post, I will go over how to create a webapp using Dash by Plotly. By the end of this blog, we’ll be able to create a website that accepts user input!
Function to Create the Database of Messages
We’ll first make a function to set up a database to receive messages from users. This is what the function looks like:
import sqlite3message_db =Nonedef get_message_db():"""creates database of messages, creates a `messages` table if not already in database, and return the connection of message_db Returns: message_db: connection to the message_db database """global message_dbif message_db isnotNone: # if database is not emptyreturn message_dbelse:# Connect to the database messages_db.sqlite message_db = sqlite3.connect("messages_db.sqlite", check_same_thread=False)# SQL command to create a `messages` table in # the database if it does not exist cmd =''' CREATE TABLE IF NOT EXISTS messages ( handle TEXT NOT NULL, message TEXT NOT NULL ) ''' cursor = message_db.cursor() cursor.execute(cmd) message_db.commit() # saves changes cursor.close() # closes cursorreturn message_db# setting up `message` tableget_message_db()
<sqlite3.Connection at 0x1061506d0>
Function to Insert a User’s Message into Database
Next, we’ll create a function that inserts a user’s inputted message into the database we just created.
def insert_message(handle, message):""" Inserts a new message into the database. Args: handle (str): The user handle. message (str): The content of the message. """# creating a cursor to our database cur = message_db.cursor() cur.execute("""INSERT INTO messages (handle, message) VALUES (?, ?) """, (handle, message))# committing changes to enure row insertion is saved message_db.commit() cursor.close() # closing cursor message_db.close() # closing connection to database
Callback Function to Update Components
Now, we’ll create a callback function to update the components. Before doing so, we need to define our Dash app. Then we’ll implement the callback function submit() to allow user to submit their message along with their name or handle.
import dashfrom dash import html, dcc, Input, Output, State# creating Dash appapp = dash.Dash(__name__)app.layout = html.Div([# page title html.H1("A SIMPLE MESSAGE BANK", style = {'font-family': 'Arial, sans-serif', 'color': '#0F807A'}),# form for submission html.H2("Submit", style = {'font-family': 'Arial, sans-serif', 'color': '#0B5551'}), html.Div("Your Message:", style={'font-family': 'Arial, sans-serif', 'color': '#678D8B'}), dcc.Input(id='user-message', type='text', style={'width': '50%', 'margin-bottom': '5px'}), html.Div("Your Name or Handle:", style={'font-family': 'Arial, sans-serif', 'color': '#678D8B'}), dcc.Input(id='user-handle', type='text', style={'width': '50%', 'margin-bottom': '5px'}), html.Button('Submit', id='submit-button', style={'margin-top': '10px', 'background-color': '#0B5551', 'color': 'white', 'border': 'none'}), html.Div(id='message-output'),# to view submitted messages html.H2("View", style = {'font-family': 'Arial, sans-serif', 'color': '#0B5551'}), html.Button('Update', id='refresh-button', style={'background-color': '#4A708B', 'color': 'white'}), html.Div(id='messages-display')])# define callback function to handle form submission@app.callback( Output('message-output', 'children'), Input('submit-button', 'n_clicks'), [State('user-handle', 'value'), State('user-message', 'value')], prevent_initial_call=True)def submit(n_clicks, handle, message):ifnot handle ornot message: # if user didn't input bothreturn'Please enter both a handle and a message.'try: insert_message(handle, message) return'Thank you for submitting a message!'exceptExceptionas e: # return error message if failed to insert messagereturnf'An error occurred: {str(e)}'df = sqlite3.connect("messages_db.sqlite", check_same_thread=False)# Run the appif__name__=='__main__': app.run_server(debug=True)
Function to Fetch Random Messages
Then, we’ll create a function to fetch random messages in our database.
def random_messages(n):""" Fetches a random selection of messages from the database. Args: n (int): Number of random messages to retrieve. Returns: list of tuples: A list of messages with their handles. """# connect to database db = get_message_db()# create a cursor cursor = db.cursor()# extracting n random messages query ="SELECT name_or_handle, message FROM messages ORDER BY RANDOM() LIMIT ?" cursor.execute(query, (n,)) messages = cursor.fetchall()# close cursor and connection to database cursor.close() db.close()return messages
Callback Function to Display Random Messages
@app.callback( Output('messages-display', 'children'), Input('refresh-button', 'n_clicks'), prevent_initial_call=True)def view(n_clicks):try: messages = random_messages(5) # extracting 5 random messagesreturn [# displays each message in one line html.Div([ html.P(message, style={'font-size': '16px'}), html.P(f"- {handle}", style={'font-size': '16px', 'text-align': 'right'}) ], style={'margin-bottom': '20px', 'border-bottom': '1px solid #ccc', 'padding-bottom': '10px'})for handle, message in messages ]exceptExceptionas e:# return error message if failed to fetch messagesreturn html.Div(f"Failed to fetch messages: {str(e)}")
To View Final Results
We’ll compile all our functions, update our Dash app to display messages that were submitted, and try using our message bank!
import sqlite3import dashfrom dash import html, dcc, Input, Output, Statemessage_db =Nonedef get_message_db():"""creates database of messages, creates a `messages` table if not already in database, and return the connection of message_db Returns: message_db: connection to the message_db database """global message_dbif message_db isnotNone: # if database is not emptyreturn message_dbelse:# Connect to the database messages_db.sqlite message_db = sqlite3.connect("messages_db.sqlite", check_same_thread=False)# SQL command to create a `messages` table in the database if it does not exist cmd =''' CREATE TABLE IF NOT EXISTS messages ( handle TEXT NOT NULL, message TEXT NOT NULL ) ''' cursor = message_db.cursor() cursor.execute(cmd) message_db.commit() # saves changes cursor.close() # closes cursorreturn message_db# setting up `message` tableget_message_db()app = dash.Dash(__name__)app.layout = html.Div([# page title html.H1("A SIMPLE MESSAGE BANK", style = {'font-family': 'Arial, sans-serif', 'color': '#0F807A'}),# form for submission html.H2("Submit", style = {'font-family': 'Arial, sans-serif', 'color': '#0B5551'}), html.Div("Your Message:", style={'font-family': 'Arial, sans-serif', 'color': '#678D8B'}), dcc.Input(id='user-message', type='text', style={'width': '50%', 'margin-bottom': '5px'}), html.Div("Your Name or Handle:", style={'font-family': 'Arial, sans-serif', 'color': '#678D8B'}), dcc.Input(id='user-handle', type='text', style={'width': '50%', 'margin-bottom': '5px'}), html.Button('Submit', id='submit-button', style={'margin-top': '10px', 'background-color': '#0B5551', 'color': 'white', 'border': 'none'}), html.Div(id='message-output'),# to view submitted messages html.H2("View", style = {'font-family': 'Arial, sans-serif', 'color': '#0B5551'}), html.Button('Update', id='refresh-button', style={'background-color': '#4A708B', 'color': 'white'}), html.Div(id='messages-display')])def insert_message(handle, message):with sqlite3.connect("messages_db.sqlite") as conn: cur = conn.cursor() cur.execute("""INSERT INTO messages (handle, message) VALUES (?, ?)""", (handle, message)) conn.commit()def random_messages(n):with sqlite3.connect("messages_db.sqlite") as conn: cur = conn.cursor() cur.execute("""SELECT handle, message FROM messages ORDER BY RANDOM() LIMIT ?""", (n,)) messages = cur.fetchall()return messages@app.callback( Output('message-output', 'children'), Input('submit-button', 'n_clicks'), [State('user-handle', 'value'), State('user-message', 'value')], prevent_initial_call=True)def submit(n_clicks, handle, message):ifnot handle ornot message:return'Please enter both a handle and a message.'try: insert_message(handle, message)return'Thank you for submitting a message!'exceptExceptionas e:returnf'An error occurred: {str(e)}'@app.callback( Output('messages-display', 'children'), Input('refresh-button', 'n_clicks'), prevent_initial_call=True)def view(n_clicks):try: messages = random_messages(5) # extracting 5 random messagesreturn [# displays each message in one line html.Div([ html.P(message, style={'font-size': '16px'}), html.P(f"- {handle}", style={'font-size': '16px', 'text-align': 'right'}) ], style={'margin-bottom': '20px', 'border-bottom': '1px solid #ccc', 'padding-bottom': '10px'})for handle, message in messages ]exceptExceptionas e:# return error message if failed to fetch messagesreturn html.Div(f"Failed to fetch messages: {str(e)}")if__name__=='__main__': app.run_server(debug=True)