Streamlit Handler Class

The class is to help with creating the Streamlit widgets and communication between the widgets and the databasee.

Three classes inherit from the StreamlitHandler class

  • StreamlitAddData
  • StreamlitEditData
  • StreamlitDeleteData

The three classes as you can guess relates to the app’s corresponding page.

StreamlitHandler – Base

I won’t go through all of the attributes, most are self explaintory. However, the one thing to mention is that the class uses two other classes, the PandasSQLHandler and the DataHandler class. We will discuss those classes further on in the tutorial.

Methods

_load_query

Read the query file stored in /query directory. Name of file needs to match the table name which is displayed in the drop down box. The names of the tables to be displayed are configured in the config / sql_column_config.yaml file.

__set_primary_key_column_name

sets the primary key column name defined in the config/sql_column_config.yaml file.

__set_column_order

sets the column order for the data_editor widgets, while excluding the primary key column. The values and order are defined in the config/sql_column_config.yaml file. The data_editor widgets will display the columns in the same order as defined in the configuration file.

fetch_row_count

Fetch number of rows in the table, used in pagination.

Will run a quick query, The query to use is defined in the config/sql_column_config.yaml file. In our tutorial we are connecting to Microsoft SQL database. Instead of doing a row_count query which mayy be expensive, will read from the sys.dm_db_partition_stats table which doesn’t require elevated privileges. If the user has access to read / write to tables they should be able to read from sys.dm_db_partition_stats.

fetch_table_data

Method will query the database, using the PandasSQLHandler class. Storing the results to be sent to the data_editor widget.

jump_current_page

Will query the source table, inclusive of prior database commits and based on user selected number of rows to display and total rows in the table will jump to the specified page. The requested page is read from Streamlist session_state dictionary. Conditional logic is in place to prevent from requesting a page that doesn’t exist.

move_current_page

Will query the source table, inclusive of prior database commits and based on user selected number of rows to display and total rows in the table will move back or forward one page. Using call backs from the nav control buttons, determines the user requested action. Conditional logic is in place to prevent from requesting a page that doesn’t exist.

input_page_select

Returns a Streamlit number_input widget. The widget allows user to input which page number they want to jump too. The widget is used in the page navigation controls show in the sidebar.

The method will return five streamlit widgets that help the user navigate between pages in the data_editor widget. I used st.markdown widget to pass the label and in the current page information. The other benefit is that you can pass css style properties. You do have to use the unsafe_allow_html property to True, for the Streamlit to apply the css style properties.

The buttons will navigate to prior page or next page, and use a call back to move_current_page method.

selectbox_rows_per_page

Returns a select box that allows the user to determine how many rows to show in the data_editor widgets. The values are defined in the config / streamlit_config.yaml file.

selectbox_table

Returns a streamlit select_box widget, listing the schema + table name to the user. The schema and table names are listed in the config / sql_column_config.yaml file. The select_box widget is wrapped in a container allowing for formatting the width on the page. Default behavior is for the select_box widget to use the full width of the page.

query_success

Returns a Boolean, indicates if the last query run was completed successfully.

update_rows_per_page

Reads from the streamlit sesssion_state dictionary, number of rows per page to return.


StreamlitAddData

The class inherits from the StreamlitHandler class with additional methods for adding rows to the table.

Methods

fetch_empty_table

Create the streamlit data_editor widget. However we need to know which columns and their corresponding datatypes to add to the data_editor widget. In order to do so wee will query the meta data of the table using the get_table_columns method from the data_handler class. The method will also align the data types from Microsoft SQL to pandas dataframe datatypes. Additionally we will only show to the user, the columns specified in the config file, config / sql_column_config.yaml

add_source_data

Now, we want to add the user input as a row to the table. The data will be passed from the data_editor widget to thhe database using the data_handler add_row method. We loop through the data_editor rows because the user may try adding multiple rows at the same time. If all of the rows are added successfully we set the _query_success flag to True. The flag is used by the query_success method.


StreamlitEditData

The class inherits from the StreamlitHandler class with additional methods for editing rows in the table.

Methods

data_editor_formatted

Using the fetch_table_data method will fetch the data from the source table. Will pass the offset and number of rows to return to the query to the row_params parameter. The values have to be passed as a tuple.

Return the streamlit data_editor widget to the user.

update_source_data

First we do a comparison to the source data and the data_editor widget data. Both sets are data are stored in a Pandas data frame allowing us to quickly check if they are equal.

If they are not equal, we grab the changes by using the data frame .compare method.

Next we loop through the rows and columns to determine what has changed. We only want to update the column data that has changed. We store the changes in the update_data in a dictionary variable.

Lastly we call the data_handler update_row method to update the source table. The method allows for sending multiple row updates. However each row that has changed will create an UPDATE sql statement to be executed.

Lastly if all the updates have been process the we set the _query_success flag to True. The flag is used by the query_success method.


StreamlitDeleteData

The class inherits from the StreamlitHandler class with additional methods for editing rows in the table.

Although in the tutorial I am showing how to delete the rows, I would suggest only deleting table rows when you are keeping table history. If don’t have temporal (system-versioned) tables I would suggest the table structure uses a delete column to mark the row as deleted. And you an update query to change the column value.

Methods

data_editor_formatted

Using the fetch_table_data method will fetch the data from the source table. Will pass the offset and number of rows to return to the query to the row_params parameter. The values have to be passed as a tuple.

Once the data is returned will add a column to the data frame named Select, and set its value to False. The column will shown as a checkbox in the data_editor widget.

Next we reset the column order so the first column is the Select column.

Lastly, return the streamlit data_editor widget to the user.

prompt_for_confirmation

First will reset the flag deletion_requested to False, so we don’t try and delete the same rows twice, if the deletion fails.

Next will extract all of the primary key ids that have been selected. In the delete_row.py callback to delete_source_data, we filtered the rows being passed to the method through the args.

The Pandas data frame query method ensures we are only deleting rows that the user selected.

Next page will talk about the DataHandler Class