Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask/Werkzeug, how to return previous page after login

Tags:

I am using the Flask micro-framework which is based on Werkzeug, which uses Python.

Before each restricted page there is a decorator to ensure the user is logged in, currently returning them to the login page if they are not logged in, like so:

# 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)     ### ... ### 

After logging in, it needs to return users to the page that took them to the login page. It also needs to retain things such as the passed variables (i.e. the entire link basically www.example.com/download_file?id=3 )

Does anyone know how to do this?

Thank you for your help :-)

like image 269
Jon Cox Avatar asked Sep 10 '10 16:09

Jon Cox


People also ask

How do I redirect a previous page in Flask?

Another method you can use when performing redirects in Flask is the url_for() function. The way that url_for() works is instead of redirecting based on the string representation of a route, you provide the function name of the route you want to redirect to.

How do I get back to Flask homepage?

If you want to be able to go back, use the following code: #base. html (this code should be in every template) window.

How do I return a redirected Flask?

Flask – Redirect & ErrorsFlask class has a redirect() function. When called, it returns a response object and redirects the user to another target location with specified status code. location parameter is the URL where response should be redirected. statuscode sent to browser's header, defaults to 302.


2 Answers

I think standard practice is to append the URL to which the user needs to be redirected after a successful login to the end of the login URL's querystring.

You'd change your decorator to something like this (with redundancies in your decorator function also removed):

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 

You'll have to substitute something for get_current_url(), because I don't know how that's done in Flask.

Then, in your login handler, when the user successfully logs in, you check to see if there's a next parameter in the request and, if so, you redirect them to that URL. Otherwise, you redirect them to some default URL (usually /, I guess).

like image 127
Will McCutchen Avatar answered Sep 29 '22 14:09

Will McCutchen


You could use a query string to keep the file info intact over a click or two. One of the nice things about url_for is how it passes unknown parameters as query strings. So without changing your registration page too much you could do something like this:

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 

Here wantsurl will keep track of the url the user landed on. If an unregistered user goes to /download/some/file.txt, login_required will send you to /register?wantsurl=%2Fdownload%2Fsome%2Ffile.txt Then you add a couple of lines to your registration function:

@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']) 

That would automatically redirect to the download on successful registration, provided you have something in the form called 'wantsurl' with the value of qs, or you could have your form submit with a query string; that could just be a little if-else in the template.

like image 32
unmounted Avatar answered Sep 29 '22 16:09

unmounted