I am using st.data_editor and is it ALMOST working correctly.
I have a pseudo-ORM list of objects connected to streamlit. I want to set it up that whenever a cell is edited, the value is immediately updated in the database.
I use the edited_rows state variable to know what was changed, and pass it back to the ORM objects using setattr(obj, changed_key, new_value).
However, I notice that after I make a second edit, both edits appear in the edited_rows dictionary. This causes my setup to handle the same change multiple times.
I tried clearing it using st.session_state[key]["edited_rows"].clear() but that did not have any effect.
Is this intentional behavior? Is there a solution for this use case?
The behavior you’re experiencing with the edited_rows dictionary in Streamlit’s st.data_editor is intentional. The edited_rows dictionary accumulates all the edits made in the data editor until the app is rerun or the session state is reset. This behavior allows you to access and handle all the changes made by the user during the session.
To address your use case of handling each change only once, you can modify your code to keep track of the changes you have already processed. Here’s a possible approach:
Create a set to store the keys of the already processed changes:
if "processed_changes" not in st.session_state:
st.session_state.processed_changes = set()
Iterate over the edited_rows dictionary, but only process the changes that haven’t been processed before:
for row_key, changed_values in st.session_state.edited_rows.items():
if row_key not in st.session_state.processed_changes:
# Process the changes for this row
obj = your_orm_objects[row_key]
for column_key, new_value in changed_values.items():
setattr(obj, column_key, new_value)
# Add the row key to the set of processed changes
st.session_state.processed_changes.add(row_key)
By using the set processed_changes to keep track of the changes that have already been processed, you ensure that each change is handled only once, even if multiple edits occur.
Remember to adapt the code above to fit your specific use case, including the names of your ORM objects and the appropriate logic for processing the changes.
I hope this helps resolve the issue and allows you to handle each change correctly in your Streamlit app.
def _handle_table_changed(self, key_name: str):
new_state = st.session_state[key_name]
if "edited_rows" in new_state:
for index, change_dict in new_state["edited_rows"].items():
source_object = self.data[index]
for changed_field, new_value in change_dict.items():
# the getattr() check is required because streamlit does not remove entries from the modification
# dictionary.
if getattr(source_object, changed_field) != new_value:
setattr(source_object, changed_field, new_value)
# new_state["edited_rows"].clear() Disabled because no effect
def render(self, key_name: str):
st.data_editor(
self.dataframe,
column_config=self.st_column_specs,
key=key_name,
column_order=self.column_names,
hide_index=True,
on_change=self._handle_table_changed,
args=[key_name],
)
Because a row can be modified multiple times, I have to check on a per-value basis (this is the getattr line). It can theoretically cause performance issues in large sessions, but I’ll cross that bridge when we get there…
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.