I’m new to Streamlit and I’m developing an interface where users can edit multiple configuration tables. The structures of the tables are different, but all contain a column with the username that inserted/updated the data.
With the data_editor I can easily fill the column for new rows, but I can’t find a way to modify the updated rows. Is there a simple way to implement this?
Let’s say I’m User4 and I edited colA in the first row with “E”. The “User” column should be automatically updated with “User4”.
I hope my explanation is clear. Thanks in advance!
import streamlit as st
import pandas as pd
loggedinUser = "User4"
df=pd.DataFrame(
[{"colA":'A',"colB": 1,"User":'User1'},
{"colA":'B',"colB": 2,"User":'User1'},
{"colA":'C',"colB": 3,"User":'User2'},
{"colA":'D',"colB": 4,"User":'User3'},]
)
with st.form('Table'):
edit_df=st.data_editor(df,num_rows="dynamic",\
column_config={
"User": st.column_config.TextColumn(
'User',
help = 'Current Logged User',
default = loggedinUser
)
})
submit_button = st.form_submit_button('Submit')
if submit_button:
try:
st.success('SUCCESS')
except Exception as e:
st.error(e)
Hi, not as elegant as the new row, but you can ‘simulate’ this with a st.rerun each time you modify a row :
loggedinUser = "User4"
df = pd.DataFrame(
[{"colA": 'A', "colB": 1, "User": 'User1'},
{"colA": 'B', "colB": 2, "User": 'User1'},
{"colA": 'C', "colB": 3, "User": 'User2'},
{"colA": 'D', "colB": 4, "User": 'User3'}, ]
)
# Initialize session state to store the original dataframe
if "original_df" not in st.session_state:
st.session_state["original_df"] = df
# Function to update user column for edited rows
def update_user_column(edited_df):
original_df = st.session_state["original_df"]
for index, row in edited_df.iterrows():
if not original_df.iloc[index].equals(row):
edited_df.at[index, "User"] = loggedinUser
return edited_df
# Display the data editor
edit_df = st.data_editor(
st.session_state["original_df"],
num_rows="dynamic",
column_config={
"User": st.column_config.TextColumn(
'User',
help='Current Logged User',
default=loggedinUser,
disabled=True # Make User column not editable directly by the user
)
},
key="data_editor"
)
if not edit_df.equals(st.session_state["original_df"]):
st.session_state["original_df"] = update_user_column(edit_df)
st.rerun()
@Faltawer you got the idea, but this solution fails to add new rows.
I also need the st.form. The DF is saved as a table when the submit button is pressed.
IndexError: single positional indexer is out-of-bounds
Traceback:
File "/usr/lib/python_udf/253c7765317f7edc435b297bf36bfec4180ecaae607b703adbcd0bce9b12d660/lib/python3.8/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 600, in _run_script
exec(code, module.__dict__)
File "/tmp/appRoot/streamlit_app.py", line 41, in <module>
st.session_state["original_df"] = update_user_column(edit_df)
File "/tmp/appRoot/streamlit_app.py", line 21, in update_user_column
if not original_df.iloc[index].equals(row):
File "/usr/lib/python_udf/253c7765317f7edc435b297bf36bfec4180ecaae607b703adbcd0bce9b12d660/lib/python3.8/site-packages/pandas/core/indexing.py", line 1103, in __getitem__
return self._getitem_axis(maybe_callable, axis=axis)
File "/usr/lib/python_udf/253c7765317f7edc435b297bf36bfec4180ecaae607b703adbcd0bce9b12d660/lib/python3.8/site-packages/pandas/core/indexing.py", line 1656, in _getitem_axis
self._validate_integer(key, axis)
File "/usr/lib/python_udf/253c7765317f7edc435b297bf36bfec4180ecaae607b703adbcd0bce9b12d660/lib/python3.8/site-packages/pandas/core/indexing.py", line 1589, in _validate_integer
raise IndexError("single positional indexer is out-of-bounds")
def update_user_column(edited_df):
original_df = st.session_state["original_df"]
for index, row in edited_df.iterrows():
if index < len(original_df) and not original_df.iloc[index].equals(row):
edited_df.at[index, "User"] = loggedinUser
return edited_df