在Flask中,如何在单击按钮时生成动态URL?

时间:2018-08-01 18:10:10

标签: python html flask

例如,现在,如果我在表单元素中有两个按钮,则单击它们中的任何一个时,您将被定向到相应的配置文件。

<form action="{{ url_for('getProfile') }}" method="post">
    <button type="submit" name="submit" value="profile1"> View Profile</button>
    <button type="submit" name="submit" value="profile2"> View Profile</button>
</form>

在我的apprunner.py中,

 @app.route('/profile', methods=['POST'])
 def getProfile():
       if request.form['submit'] = 'profile1':
            return render_template("profile1.html")
       else if request.form['submit'] = 'profile2':
            return render_template("profile2.html")

但是,我的问题是,当我单击任一按钮时,URL总是像“ 127.0.0.1:5000/profile”。但是,我希望它看起来像“ http://127.0.0.1:5000/profile1”或“ http://127.0.0.1:5000/profile2”。

我一直在寻找有关如何在线生成动态URL的解决方案,但是它们都不适合单击按钮。

谢谢!

2 个答案:

答案 0 :(得分:3)

@app.route('/profile<int:user>')                                                                                                   
def profile(user):                                                                                                             
    print(user)

您可以在REPL上对其进行测试:

import flask
app = flask.Flask(__name__)

@app.route('/profile<int:user>')
def profile(user):
    print(user)

ctx = app.test_request_context()
ctx.push()

flask.url_for('.profile', user=1)
'/profile1'

编辑:

如何将user参数传递到新路线取决于您的需求。如果您需要profile1profile2的硬编码路由,则可以分别传递user=1user=2。如果要以编程方式生成这些链接,则取决于这些配置文件的存储方式。

否则,您可以将redirect而不是render_template移至url_for,并在请求对象中包含已解析的元素。这意味着有两条路线

@app.route('/profile<int:user>')
def profile_pretty(user):
    print(user)

@app.route('/profile', methods=['POST'])
def getProfile():
      if request.form['submit'] = 'profile1':
           return redirect(url_for('.profile_pretty', user=1))
       else if request.form['submit'] = 'profile2':
            return redirect(url_for('.profile_pretty', user=2))
  

小凹坑:这会使您的路线看起来像您想要的那样,但这效率低下,因为它每次都会生成一个新请求,只是以您想要的方式生成网址。此时,可以安全地问为什么您要动态生成静态内容的路由。


http://exploreflask.com/en/latest/views.html#url-converters

中所述
  

在Flask中定义路线时,您可以指定要转换为Python变量并传递给视图函数的部分。

@app.route('/user/<username>')
def profile(username):
    pass
  

标记为URL的部分中的任何内容都将作为用户名参数传递给视图。您还可以指定一个转换器,以在将变量传递到视图之前对其进行过滤。

@app.route('/user/id/<int:user_id>')
def profile(user_id):
    pass
  

在此代码块中,URL http://myapp.com/user/id/Q29kZUxlc3NvbiEh将返回404状态代码-未找到。这是因为URL中应该是整数的部分实际上是一个字符串。

     

我们还可以使用第二个视图来查找字符串。将会为/ user / id / Q29kZUxlc3NvbiEh /调用,而第一个会为/ user / id / 124调用。

答案 1 :(得分:0)

首先,让我们看一下您已经编写的代码:

<form action="{{ url_for('getProfile') }}" method="post">
<button type="submit" name="submit" value="profile1" View Profile</button>
<button type="submit" name="submit" value="profile1" View Profile</button>
</form>

我想说的第一件事是,如果我是你,我会缩进两个按钮标签,因为它们位于表单标签内,并且我认为当您拥有较大的HTML文件时,它可以使事情变得整洁。但是,这只是我的偏爱,并不完全与问题相关。

第二,您的第二个按钮标签似乎是多余的,因为它与第一个相同。也许您是说第二个按钮的值为“ profile2”?

无论如何,目前看来您是在以静态方式进行设计,即为每个配置文件使用静态html文件,并为加载每个不同的html文件使用多个if语句。就个人而言,我建议您动态地执行配置文件之类的操作,因为这样以后将来添加更多的配置文件会变得更加容易。

但是,如果您不愿意以静态方式执行此操作,则理论上它应该可以进行以下更改:

<form action="{{ url_for('getProfile') }}" method="post">
    <button type="submit" name="submit" value="profile1" View Profile</button>
    <button type="submit" name="submit" value="profile2" View Profile</button>
</form>

注意:这只会加载正确的配置文件,据我所知,如果两个配置文件都是从同一端点(或视图功能)加载的,则无法更改显示的网址

这是我将如何做的简要概述,以一种更加RESTful和动态的方式:

首先,我希望view函数从URL中获取一个参数,该参数是要加载的配置文件:

@app.route('/profiles/<profile>') # parts of an endpoint's URL in <> mean it can be
def profile(profile):             # passed into a view function as a parameter
    return render_template('path/to/profile.html', profile=profile)

然后我将让函数简单地渲染一个名为profile.html的模板,并将其传递给配置文件编号。在html模板内部,它查看使用Jinja之类传递的配置文件编号,并根据配置文件编号显示不同的内容。

然后,您的按钮必须分别链接到网址“ / profiles / 1”和“ / profiles / 2”

根据配置文件本身的组成,我还建议研究使用Flask使用数据库,以便可以存储每个配置文件的内容(例如名称和年龄等),然后在呈现模板时作为参数传递

强烈建议您阅读并尝试在Flask网站上阅读有关制作博客应用程序的教程,然后再继续操作