Перенаправление в приложении Plotly Dash
Я пытался разработать многостраничное шаблонное приложение от Plolty Dash. Я пытаюсь реализовать редирект при успешном входе в систему. Структура проекта выглядит следующим образом:
multipage
├── app.py
├── apps
│ ├── app1.py
│ ├── app2.py
│ ├── app3.py
├── index.py
└── static
└── base.css
Код, который у меня есть, выглядит следующим образом:
index.py (начальная точка)
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)
Здесь, когда пользователь посещает /
страница входа (app3.py) будет отображена.
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 (код входа)
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")
В функции login(username, password)
, если пользователь действителен, то приложение должно перенаправить на /home
и app1.py
должно быть оказано там.
Я был в состоянии перейти на различные страницы с взаимодействием с пользователем. Есть ли способ в тире, по которому я могу перенаправить из программы. Я действительно новичок, пожалуйста, помогите мне в том же.
1 ответ
Это похоже на то, что не должно работать, но это работает:
Сначала добавьте скрытый div для вывода вашего обратного вызова:
html.Div(id="hidden_div_for_redirect_callback")
Затем определите свой обратный вызов следующим образом (примечание: я использую 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()
Вернувшийся dcc.Location
К сожалению, страница будет перезагружена (с любыми связанными побочными эффектами), но в конечном итоге вы окажетесь на нужном пути. Если авторизация не удалась, вы просто предотвратите обновление.
Я сделал запрос извлечения с возможностью вернуть ответ Flask, но у меня нет времени, чтобы завершить его. Если вам необходимо реализовать его до того, как я рассмотрю этот PR с помощью тестов, вы можете расширить базовое приложение с этими изменениями и использовать его следующим образом:
@app.callback(...)
def login():
if username:
redirect_home = redirect('/home')
response = app.make_response(redirect_home)
return response
else:
return 'No luck'
Другой способ взлома - вернуть фрагмент javascript внутри тега, который изменяется window.location
имущество.