I have been trying to develop a multipage template app from Plolty Dash. I'm trying to implemnet a redirect on sucessful login. The structure of the project is as follows:
multipage
├── app.py
├── apps
│ ├── app1.py
│ ├── app2.py
│ ├── app3.py
├── index.py
└── static
└── base.css
The code that I have are as follows:
index.py (starting point)
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
from app import app, server
from apps import app1, app2, app3
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div(id='page-content')
])
@app.callback(Output('page-content', 'children'),
[Input('url', 'pathname')])
def display_page(pathname):
if pathname == '/':
return app3.layout
else:
return '404'
if __name__ == '__main__':
server.run(debug=True)
Here when the user vists /
the login page(app3.py) will be rendered.
app.py
import dash
import os
import flask
app = dash.Dash()
server = app.server
app.config.supress_callback_exceptions = True
external_css = [
'https://codepen.io/chriddyp/pen/bWLwgP.css',
'/static/base.css'
]
for css in external_css:
app.css.append_css({"external_url": css})
@app.server.route('/static/<path:path>')
def static_file(path):
static_folder = os.path.join(os.getcwd(), 'static')
return flask.send_from_directory(static_folder, path)
app2.py (login code)
import flask
from dash.dependencies import Input, Output, State, Event
import dash_html_components as html
import dash_core_components as dcc
from apps import app1
from app import app
layout = html.Div(children=[
# content
html.Div(id='login',children=[
html.H3("Please log in", hidden=False, id="page_header"),
# login form
html.Form(children=[
html.P(children=["Username: ", dcc.Input(type='text', id='username', placeholder='username')]),
html.P(children=["Password: ", dcc.Input(type='password', id='password', placeholder='password')]),
html.Button(children=['Login'], type='submit', id='login_button')
], style={'width': '30%', 'margin': '0 auto'}, id="login_form", hidden=False)
], style={'display': 'block', 'text-align': 'center', 'padding': 2}),
html.Br(),
html.Hr(style={'width': '30%'}),
])
@app.callback(Output('login', 'children'),
events=[Event('login_button', 'click')],
state=[State('username', 'value'), State('password', 'value')])
def login(username, password):
if username:
print("login")
return flask.redirect('/home')
else:
print("No Luck")
In the function login(username, password)
, if the user is valid, then the app should redirect to /home
and the app1.py
must be rendered there.
I was able to navigate to various pages with user interaction. Is there a way in dash by which I can redirect from the program. I'm really new to dash please help me on the same.
This seems like something that shouldn't work, yet it does:
First add a hidden div for the output of your callback:
html.Div(id="hidden_div_for_redirect_callback")
Then define your callback like this (sidenote: I am using flask_login
):
# Note that I am currently at /login
@app.callback(Output("hidden_div_for_redirect_callback", "children"),
[Input("login_button", "n_clicks")],
[State('username_login', 'value'),
State('pwsd_login', 'value'),])
def login_user_(n_clicks, uname, pswd):
# User clicked the login button
# Do login logic....
if successful_login:
return dcc.Location(pathname="/home", id="someid_doesnt_matter")
else:
# e.g. password doesn't match
raise PreventUpdate()
The returned dcc.Location
will sadly force the page to reload (with any related side-effects) but you will end up in the path you want. If the login fails, you just prevent the update.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With