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

时间:2016-01-21 16:09:18

标签: python flask flask-wtforms

我尝试学习Flask,但我无法找到问题的答案:如果我使用GET作为Flask-的表单方法,有没有办法获得一个“干净”的URL,可以加入书签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>

提交后,我收到了这个网址:

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

我可以复制此链接,将其发送给其他人,他或她可以使用浏览器打开它,并获得相同的结果。通过使用表单中的方法GET简单地完成。看看这个:

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

使用Flask I cloud执行此操作:

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 %}

1 个答案:

答案 0 :(得分:1)

我建议将其分解为自己的观点。您应该使用CSRF表单,您应该尝试分离GET和POST接口。

迫使一段代码或函数执行多项操作有时可能看起来更干净,但会发生什么情况会增加可维护性成本并使事情变得不那么清晰。

你如何在Flask中这样做:

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

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

在你的例子中,Marshmallow会有点矫枉过正,但如果你计划扩展你的API,那就太棒了。它将允许您采用更复杂的JSON blob并验证并将它们序列化为Python对象。

另外,我会研究为什么你在POST上使用GET。 POST应该用于在服务器上创建新数据,应该使用GET来获取该信息。

编辑(编辑后):

  

使用Flask I cloud执行此操作:

     

http://127.0.0.1/query/8.8.8.8   但是,如果我使用不止一个,那该怎么办?   参数?在PHP中它看起来像这样:

您可以像这样制作Flask视图:

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

但是,如果您想通过ONE表单完成所需的操作,则必须关闭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到您的OLD视图。 POST时请确保包含CSRF令牌!像这里:

{{ form.csrf_token }}