Frasco / Werkzeug, cómo devolver la página anterior después de iniciar sesión

Estoy usando el micro-marco Flask que se basa en Werkzeug, que utiliza Python.

Antes de cada página restringida, hay un decorador para garantizar que el usuario haya iniciado sesión, y actualmente los devuelve a la página de inicio de sesión si no han iniciado sesión, de este modo:

# Decorator def logged_in(f): @wraps(f) def decorated_function(*args, **kwargs): try: if not session['logged_in']: flash('Please log in first...', 'error') return redirect(url_for('login')) else: return f(*args, **kwargs) except KeyError: flash('Please log in first...', 'error') return redirect(url_for('login')) return decorated_function # Login function @app.route('/', methods=['GET', 'POST']) def login(): """Login page.""" if request.method=='POST': ### Checks database, etc. ### return render_template('login.jinja2') # Example 'restricted' page @app.route('/download_file') @logged_in def download_file(): """Function used to send files for download to user.""" fileid = request.args.get('id', 0) ### ... ### 

Después de iniciar sesión, debe devolver a los usuarios a la página que los llevó a la página de inicio de sesión. También debe conservar elementos como las variables pasadas (es decir, el enlace completo básicamente www.example.com/download_file?id=3)

¿Alguien sabe como hacer esto?

Gracias por tu ayuda 🙂

Creo que la práctica habitual es agregar la URL a la que el usuario debe ser redirigido después de un inicio de sesión exitoso al final de la cadena de consulta de la URL de inicio de sesión.

Cambiaría su decorador a algo como esto (con las redundancias en su función de decorador también eliminadas):

 def logged_in(f): @wraps(f) def decorated_function(*args, **kwargs): if session.get('logged_in') is not None: return f(*args, **kwargs) else: flash('Please log in first...', 'error') next_url = get_current_url() # However you do this in Flask login_url = '%s?next=%s' % (url_for('login'), next_url) return redirect(login_url) return decorated_function 

Tendrás que sustituir algo por get_current_url() , porque no sé cómo se hace en Flask.

Luego, en su controlador de inicio de sesión, cuando el usuario inicia sesión correctamente, verifica si hay un next parámetro en la solicitud y, si es así, los redirige a esa URL. De lo contrario, los redirecciona a alguna URL predeterminada (generalmente / , supongo).

Podría usar una cadena de consulta para mantener intacta la información del archivo con un clic o dos. Una de las cosas buenas de url_for es cómo pasa parámetros desconocidos como cadenas de consulta . Así que sin cambiar demasiado tu página de registro, podrías hacer algo como esto:

 def login_required(f): @wraps(f) def decorated_function(*args, **kwargs): if g.user is None: return redirect(url_for('register', wantsurl = request.path)) return f(*args, **kwargs) return decorated_function 

Aquí wantsurl hará un seguimiento de la URL que el usuario aterrizó. Si un usuario no registrado va a /download/some/file.txt , login_required lo enviará a /register?wantsurl=%2Fdownload%2Fsome%2Ffile.txt Luego, agregará un par de líneas a su función de registro:

 @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'GET': if 'wantsurl' in request.args: qs = request.args['wantsurl'] return render_template('register.html', wantsurl=qs) if request.method == 'POST': if 'wantsurl' in request.form and everything_else_ok: return redirect(request.form['wantsurl']) 

Eso se redirigiría automáticamente a la descarga si se registra correctamente, siempre que tenga algo en el formulario denominado ‘wantsurl’ con el valor de qs , o podría enviar el formulario con una cadena de consulta; eso podría ser un poco si no en la plantilla.