Estoy tratando de crear una aplicación Dash que esté integrada en la aplicación Flask. Todo parece estar funcionando bien, pero cuando trato de mostrar el usuario registrado en la aplicación Dash, aparece como "Ninguno".
La estructura de mi aplicación es la siguiente:
example/ example/ dashapp/ static/ custom-css.css templates/ base.html home.html login.html __init__.py app1.py forms.py models.py routes.py application.py config.py users.db Mi aplicación Dash está en app1.py He intentado varias formas de pasar current_user pero sin éxito. Sin embargo, sale bien en home.html . Supongo que el problema es que mi aplicación está en un archivo separado y no en las routes.py .
Aquí está el código para app.py :
import dash import dash_html_components as html from dashapp import application from flask_login import login_required, current_user app1 = dash.Dash(__name__, server = application, routes_pathname_prefix = '/app1/', assets_folder = 'static', assets_url_path = '/static') app1.scripts.config.serve_locally = True app1.css.config.serve_locally = True app1.layout = html.Div( children = '{}'.format(current_user) ) for view_func in app1.server.view_functions: if view_func.startswith('/app1/'): app1.server.view_functions[view_func] = login_required(app1.server.view_functions[view_func]) código routes.py :
from flask import render_template, flash, redirect, url_for, request from flask_login import login_user, logout_user, current_user, login_required from werkzeug.urls import url_parse from dashapp import application, db from dashapp.forms import LoginForm from dashapp.models import User from dashapp import app1 @application.route('/') @application.route('/home') @login_required def home(): return render_template('home.html') @application.route('/login', methods=['GET', 'POST']) def login(): if current_user.is_authenticated: return redirect(url_for('home')) form = LoginForm() if form.validate_on_submit(): user = User.query.filter_by(username=form.username.data).first() if user is None or not user.check_password(form.password.data): flash('Invalid username or password') return redirect(url_for('login')) login_user(user, remember=form.remember_me.data) next_page = request.args.get('next') if not next_page or url_parse(next_page).netloc != '': next_page = url_for('home') return redirect(next_page) return render_template('login.html', form=form) @application.route('/app1/') @application.route('/logout') def logout(): logout_user() return redirect(url_for('login'))Otros scripts son bastante estándar y no los incluiré en la pregunta a menos que sean realmente necesarios.
Por favor, sugiera cómo superar mi problema. ¡Gracias!
Me las arreglé para arreglar esto con un poco de ayuda. En caso de que alguien se quede atascado, vea el código actualizado a continuación.
Se agregaron filas de session para almacenar el nombre de usuario actual en routes.py :
from flask import render_template, flash, redirect, url_for, request, session from flask_login import login_user, logout_user, current_user, login_required from werkzeug.urls import url_parse from dashapp import application, db from dashapp.forms import LoginForm from dashapp.models import User from dashapp import app1 @application.route('/') @application.route('/home') @login_required def home(): return render_template('home.html') @application.route('/login', methods=['GET', 'POST']) def login(): if current_user.is_authenticated: session['username'] = current_user.username return redirect(url_for('home')) form = LoginForm() if form.validate_on_submit(): session['username'] = form.username.data user = User.query.filter_by(username=form.username.data).first() if user is None or not user.check_password(form.password.data): flash('Invalid username or password') return redirect(url_for('login')) login_user(user, remember=form.remember_me.data) next_page = request.args.get('next') if not next_page or url_parse(next_page).netloc != '': next_page = url_for('home') return redirect(next_page) return render_template('login.html', form=form) @application.route('/logout') def logout(): session.pop('username', None) logout_user() return redirect(url_for('login')) Y session en la devolución de llamada para app1.py :
import dash import dash_html_components as html from dash.dependencies import Input, Output from dashapp import application from flask_login import login_required from flask import session app1 = dash.Dash(__name__, server = application, routes_pathname_prefix = '/app1/', assets_folder = 'static', assets_url_path = '/static') app1.scripts.config.serve_locally = True app1.css.config.serve_locally = True app1.layout = html.Div( children = [ html.Div(id='div2'), html.Div(id='div3', children = 'xxxx'), ], ) @app1.callback( Output('div2', 'children'), [Input('div3', 'children')]) def update_intervalCurrentTime(children): return session.get('username', None) for view_func in app1.server.view_functions: if view_func.startswith('/app1/'): app1.server.view_functions[view_func] = login_required(app1.server.view_functions[view_func])Enfrentó el mismo problema. Supongo que el problema es que el usuario actual no se ha inicializado cuando la 'aplicación' registra la aplicación Dash. Buena solución, aunque parece un poco insegura ya que las sesiones de Flask solo están codificadas.
https://github.com/RafaelMiquelino/dash-flask-login/blob/master/app.py - solución más robusta en mi opinión. Comprueba current_user en las devoluciones de llamada y usa el contenido de la página como entrada, por lo que las devoluciones de llamada se llaman al cargar la página. También puede omitir la protección de las vistas si la experiencia del usuario no es un problema.
Aquí hay un ejemplo simplificado de cómo lo usé:
@app.callback( Output('graph-wrapper', 'children'), [Input('page-content', 'children')]) def load_graph(input1): if current_user.is_authenticated: return dcc.Graph() # Dash Graph populated with current_user data from db else: return ''