Nest form inside regular button

I am trying to

  1. Take some user input
  2. When a “Load” button (normal style button) is clicked, build a form from that input with N number of widgets
  3. When form_submit_button is clicked, write the widgets’ values to a database.

I’ve noted the warnings in the docs about putting a button inside a form, but there is nothing about putting a form inside a button.

Here is a minimal example where the user enters a film director’s name and the form is populated with all of their films, each with a widget to provide a rating. When I click the form_submit_button, the app resets but the code inside the if submitted: block is not executed.

Any suggestions?

import streamlit as st

director = st.text_input("Director")
load_button = st.button("Load films")

# When the load_button clicked, the form is created and populated
if load_button:
    # (Some code to fetch the film data from a database)
    # films is a list of Film objects
    films = load_films(director=director)

    # Display each film along with a widget to provide a rating
    with st.form():
        # Catch each widget in a dictionary
        widget_dict = {}

        # Add a row to the form for every film
        for film in films:
            info_col, rating_col = st.beta_columns(2)
            # Put film info in left column
            with info_col:
            # Put a widget in the right column
            with rating_col:
                rating = st.slider(
                # Add this widget to the dict
                widget_dict[film.title] = rating

        # When you submit the form, it loops through all
        # widget entries and updates an external database
        submitted = st.form_submit_button("Submit")
        if submitted:
            print(f"Submitting ratings for {director}")
            for title, rating in widget_dict.items():
                write_rating_to_db(director, title, rating)