传递参数时重定向

在烧瓶里,我可以这样做:

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

如果 foo.html 包含 {{ messages['main'] }},页面将显示 hello:

@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路由,这样我就不必在加载它之前重写该路由计算的相同逻辑代码了?

163074 次浏览

You could pass the messages as explicit URL parameter (appropriately encoded), or store the messages into session (cookie) variable before redirecting and then get the variable before rendering the template. For example:

from flask import session, url_for


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

(encoding the session variable might not be necessary, flask may be handling it for you, but can't recall the details)

Or you could probably just use Flask Message Flashing if you just need to show simple messages.

I'm a little confused. "foo.html" is just the name of your template. There's no inherent relationship between the route name "foo" and the template name "foo.html".

为了实现不为两个不同的路由重写逻辑代码的目标,我只需定义一个函数并为两个路由调用该函数。我不会使用重定向,因为这实际上会重定向客户端/浏览器,这需要它们加载两个页面而不是一个页面,只是为了节省一些编码时间-这似乎意味着:-p

So maybe:

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"})

I feel like I'm missing something though and there's a better way to achieve what you're trying to do (I'm not really sure what you're trying to do)

I found that none of the answers here applied to my specific use case, so I thought I would share my solution.

I was looking to redirect an unauthentciated user to public version of an app page with any possible URL params. Example:

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

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

Here's the solution that worked for me.

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

Hope this helps someone!

You can however maintain your code and simply pass the variables in it separated by a comma: if you're passing arguments, you should rather use render_template:

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