I'm trying to build a small form with dash
and dash-bootstrap-components
, but I can't figure out how to use the 'action' attribute of the form.
Or, rather, I'm trying to save the data that the user inputs into the form to the Postgres DB, and the action
attribute seems to be the way to do that, but I wasn't able to find any examples on how to use it.
Did anybody have experience building forms with DBC?
EDIT my current solution is (in a simplified form):
def handle_submit(n_submit, e, pass):
username = e.split('@')
pg = pd.DataFrame(e, username, pass)
if n_submit:
pg.to_sql("table", con=db.engine, if_exists="append", index=False)
return 'success'
but that doesn't seem to work.
By default the action
endpoint isn't used
prevent_default_on_submit (boolean; default True): The form calls preventDefault on submit events. If you want form data to be posted to the endpoint specified by action on submit events, set prevent_default_on_submit to False. Defaults to True.
Based on your question it seems you just want to do something on submit and have no need for the action
. In this case you can do something like this:
from dash import Dash
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Output, Input, State
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
form = dbc.Form(
id="form",
children=[
dbc.FormGroup(
[
dbc.Label("Email", className="mr-2"),
dbc.Input(id="email", type="email", placeholder="Enter email"),
],
className="mr-3",
),
dbc.FormGroup(
[
dbc.Label("Password", className="mr-2"),
dbc.Input(id="password", type="password", placeholder="Enter password"),
],
className="mr-3",
),
dbc.Button("Submit", color="primary"),
],
inline=True,
)
app.layout = html.Div([form, html.Div(id="output")])
@app.callback(
Output("output", "children"),
Input("form", "n_submit"),
State("email", "value"),
State("password", "value"),
prevent_initial_call=True
)
def handle_submit(n_submit, email, password):
# Do stuff...
return n_submit
if __name__ == "__main__":
app.run_server()
n_submit
is returned in the callback above in order to show that the submit action works, but you probably want to change this to something else according to your needs.
Update
Based on your edit you could change the callback to something like this:
@app.callback(
Output("output", "children"),
Input("form", "n_submit"),
State("email", "value"),
State("password", "value"),
prevent_initial_call=True,
)
def handle_submit(n_submit, email, password):
username = email.split("@")
pg = pd.DataFrame(
{"email": [email], "username": [username], "password": [password]}
)
if n_submit:
pg.to_sql("table", con=db.engine, if_exists="append", index=False)
return "success"
return ""
I've changed the way the DataFrame is constructed and the variable names. pass
is a reserved keyword so I wouldn't use that as a parameter name. I've also added a default return statement. Not really necessary here as prevent_initial_call
is set to True
, but it shows how you could account for the case that n_submit
were to evaluate to False
.