Перенаправление при передаче аргументов

В колбе я могу сделать это:

render_template("foo.html", messages={'main':'hello'})

И если foo.html содержит {{ messages['main'] }}, страница покажет hello, Но что, если есть маршрут, который ведет к foo:

@app.route("/foo")
def do_foo():
    # do some logic here
    return render_template("foo.html")

В этом случае единственный способ получить доступ к файлу foo.html, если я так или иначе хочу, чтобы это происходило, - это через redirect:

@app.route("/baz")
def do_baz():
    if some_condition:
        return render_template("baz.html")
    else:
        return redirect("/foo", messages={"main":"Condition failed on page baz"}) 
        # above produces TypeError: redirect() got an unexpected keyword argument 'messages'

Итак, как я могу получить это messages переменная для передачи в foo маршрут, так что мне не нужно просто переписать тот же логический код, который этот маршрут вычисляет, прежде чем загрузить его?

5 ответов

Решение

Вы можете передать сообщения как явный параметр URL (соответствующим образом закодированный) или сохранить сообщения в session (cookie) перед перенаправлением, а затем получить переменную перед рендерингом шаблона. Например:

def do_baz():
    messages = json.dumps({"main":"Condition failed on page baz"})
    session['messages'] = messages
    return redirect(url_for('.do_foo', messages=messages))

@app.route('/foo')
def do_foo():
    messages = request.args['messages']  # counterpart for url_for()
    messages = session['messages']       # counterpart for session
    return render_template("foo.html", messages=json.loads(messages))

(кодирование переменной сеанса может быть необязательным, колба может обработать это для вас, но не может вспомнить детали)

Или вы можете просто использовать Flask Message Flashing, если вам просто нужно показывать простые сообщения.

Я обнаружил, что ни один из ответов здесь не относится к моему конкретному варианту использования, поэтому я решил поделиться своим решением.

Я искал перенаправления неаутентифицированного пользователя в публичную версию страницы приложения с любыми возможными параметрами URL. Пример:

/app/4903294/my-great-car?email=coolguy%40gmail.com для

/public/4903294/my-great-car?email=coolguy%40gmail.com

Вот решение, которое сработало для меня.

return redirect(url_for('app.vehicle', vid=vid, year_make_model=year_make_model, **request.args))

Надеюсь, это поможет кому-то!

Я немного запутался. "foo.html" - это просто название вашего шаблона. Между именем маршрута "foo" и именем шаблона "foo.html" нет внутренней связи.

Чтобы достичь цели не переписывать логический код для двух разных маршрутов, я бы просто определил функцию и вызвал ее для обоих маршрутов. Я бы не использовал перенаправление, потому что это на самом деле перенаправляет клиент / браузер, который требует, чтобы они загружали две страницы вместо одной, просто чтобы сэкономить вам некоторое время кодирования - что, кажется, означает:-P

Так что, может быть:

def super_cool_logic():
    # execute common code here

@app.route("/foo")
def do_foo():
    # do some logic here
    super_cool_logic()
    return render_template("foo.html")

@app.route("/baz")
def do_baz():
    if some_condition:
        return render_template("baz.html")
    else:
        super_cool_logic()
        return render_template("foo.html", messages={"main":"Condition failed on page baz"})

Хотя я чувствую, что что-то упустил, и есть лучший способ добиться того, что вы пытаетесь сделать (я не совсем уверен, что вы пытаетесь сделать)

Я хочу упомянуть, что url_for нельзя использовать, пока он не добавлен в колбу для импорта!

Я потратил час, пытаясь выяснить, почему это не сработает, поскольку никто не упомянул об этом на нескольких сайтах!!!

добавлять url_for в список импорта, как это:

from flask import Flask, render_template, request, redirect, session, url_for

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

@app.route("/baz")def do_baz():if some_condition:return render_template("baz.html") else: return render_template("/foo", messages={"main": "Ошибка на странице baz"})

Другие вопросы по тегам