如何获得可以在 Flask-WTF 中添加书签的“漂亮”URL?

How to get a “nice” URL that can be bookmarked in Flask-WTF?

我尝试学习 Flask,但我找不到问题的答案:如果我使用 GET 作为表单方法,有没有办法获得一个“干净”URL,可以添加书签使用 Flask-WTF 插件?

如果我在模板中使用方法 POST:

<form method="POST" action="">

浏览器中的URL不会改变,在Flask的调试模式下会是:

http://127.0.0.1:5000/

如果我提交表格。

如果我使用 GET 方法,URL 将如下所示:

http://127.0.0.1:5000/?name=test&submit=Submit&csrf_token=1453393786%23%23a327427d

但我想使用 Flask-WTF 插件来制作表格并在浏览器中取回一个漂亮的、可收藏的 URL,如下所示:

http://127.0.0.1:5000/?name=test

这可能吗?

我尝试实现的是 PHP 中的类似内容:

<?php
   if( $_GET["name"] ) {
        echo "Hello, ". $_GET['name']. "!";
        exit();
    }
?>
<html>
   <body>

      <form action = "<?php $_PHP_SELF ?>" method = "GET">
         Name: <input type = "text" name = "name" />
         <input type = "submit" />
      </form>

   </body>
</html>

提交后,我得到这个URL:

http://127.0.0.1/test.php?name=test

我可以复制这个link,发给别人,他或她可以用浏览器打开它,得到同样的结果。只需在表单中使用 GET 方法即可轻松完成。看看这个:

http://www.utrace.de/?query=8.8.8.8

使用 Flask 我云执行此操作:

http://127.0.0.1/query/8.8.8.8

但是,如果我要使用多个参数呢?在 PHP 中,它看起来像这样:

http://127.0.0.1/?para1=8.8.8.8&para2=US

我试过了,使用这个代码(借自 Miguel Grinberg):

节目:

from flask import Flask, render_template
from flask.ext.wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import Required, Length

app = Flask(__name__)
app.config['SECRET_KEY'] = 'top secret!'

class NameForm(Form):
    name = StringField('What is your name?', validators=[Required(),
                                                         Length(1, 16)])
    submit = SubmitField('Submit')

@app.route('/', methods=['GET', 'POST'])
def index():
    name = None
    form = NameForm()
    if form.validate_on_submit():
        name = form.name.data
        form.name.data = ''
    return render_template('index.html', form=form, name=name)

if __name__ == '__main__':
    app.run(debug=True)

模板:

<form method="GET" action="">
    {{ form.name.label }} {{ form.name(size=16) }}
    {% for error in form.name.errors %}
        {{ error }}
    {% endfor %}
     <br>
    {{ form.submit() }}
    {{ form.hidden_tag() }}
</form>
    {% if name %}
        <h1>Hello, {{ name }}!</h1>
    {% endif %}

我建议将其纳入自己的观点。您应该对表单使用 CSRF,并且您应该尝试将 GET 和 POST 接口分开。

强制一段代码或函数做多项事情有时看起来更简洁,但实际上会增加可维护性成本并使事情变得不那么清晰。

如何在 Flask 中执行此操作:

@app.route('/<name>/', methods=['GET'])

现在,这并没有给你验证。您可以自己执行此操作,也可以使用 Marshmallow 等库:https://marshmallow.readthedocs.org/en/latest/

在您的示例中,Marshmallow 可能有点矫枉过正,但如果您打算扩展 API,那会很棒。它将允许您获取更复杂的 JSON blob,并将它们验证并序列化为 Python 个对象。

此外,我会调查您为什么使用 GET 而不是 POST。 POST 应该用于在服务器上创建新数据,GET 应该用于获取该信息。

编辑(编辑后):

With Flask I cloud do this:

http://127.0.0.1/query/8.8.8.8 But what, if I would use more than one parameter? In PHP it would look like this:

您可以像这样创建 Flask 视图:

@app.route('/<name>/<another_parameter>/<another>/', methods=['GET'])
def some_route_name(name, another_parameter, another):

但是,如果你想用一个表单完成你想要的,你就必须关闭 CSRF。您的 PHP 示例未使用 CSRF。

我建议:

1) 按照我最初的建议创建一个新视图 2) 在您使用表单的视图中,将其 POST 设置为自身,然后重定向到新视图,如下所示:

if form.validate_on_submit():
    return redirect(url_for('name_of_new_view', name=form.name.data))

3) 在此新视图中,放置您的表单,但将该表单 POST 放入旧视图。请确保在 POST 时包含 CSRF 令牌!喜欢这里:

{{ form.csrf_token }}