Flask / Werkzeug, как вернуться на предыдущую страницу после входа в систему

Я использую микро-фреймворк Flask, основанный на Werkzeug, который использует Python.

Перед каждой закрытой страницей есть декоратор, гарантирующий, что пользователь вошел в систему, в настоящее время возвращающий их на страницу входа, если они не вошли в систему, например:

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

После входа в систему необходимо вернуть пользователей на страницу, которая привела их на страницу входа. Он также должен сохранять такие вещи, как переданные переменные (т.е. вся ссылка в основном www.example.com/download_file?id=3)

Кто-нибудь знает как это сделать?

Спасибо за помощь :-)


person Jon Cox    schedule 10.09.2010    source источник


Ответы (2)


Я думаю, что стандартной практикой является добавление URL-адреса, на который необходимо перенаправить пользователя после успешного входа в систему, в конец строки запроса URL-адреса входа.

Вы бы изменили свой декоратор на что-то вроде этого (с удалением избыточности в вашей функции декоратора):

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

Вам придется чем-то заменить get_current_url(), потому что я не знаю, как это делается во Flask.

Затем в обработчике входа в систему, когда пользователь успешно входит в систему, вы проверяете, есть ли в запросе параметр next, и, если да, перенаправляете его на этот URL-адрес. В противном случае вы перенаправляете их на какой-то URL-адрес по умолчанию (обычно /, я думаю).

person Will McCutchen    schedule 10.09.2010
comment
+1 см. Также первую ссылку, чтобы узнать о небольшой удобной функции фляги для этого блока else - person unmounted; 11.09.2010
comment
get_current_url () - это flask.request.url - person Dmitry Mukhin; 23.09.2011

Вы можете использовать строку запроса, чтобы сохранить информацию о файле в неизменном виде в течение одного или двух щелчков мышью. Одна из приятных особенностей url_for - это то, как он передает неизвестные параметры в виде строк запроса. Поэтому, не слишком сильно меняя страницу регистрации, вы можете сделать что-то вроде этого:

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

Здесь wantsurl будет отслеживать URL-адрес, на который перешел пользователь. Если незарегистрированный пользователь перейдет на /download/some/file.txt, login_required отправит вас на /register?wantsurl=%2Fdownload%2Fsome%2Ffile.txt Затем вы добавите пару строк в свою функцию регистрации:

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

Это автоматически перенаправит на загрузку при успешной регистрации, при условии, что у вас есть что-то в форме под названием «wanturl» со ​​значением qs, или вы можете отправить свою форму со строкой запроса; это могло быть просто немного if-else в шаблоне.

person unmounted    schedule 11.09.2010