【问题标题】:Flask-WTF: multiple forms of same class all returning the same data on submissionFlask-WTF:同一类的多种形式都在提交时返回相同的数据
【发布时间】:2017-12-18 14:11:46
【问题描述】:

我正在生成多个表单,每个图像一个,并将图像和相应的表单打包为列表中的元组。

然后将该列表传递给 Jinja,其中每个元组都被解包,每个图像和表单被插入到一个列表中以通过表单进行投票。

我的问题是单击任何一个特定表单都会导致所有表单返回,就像单击了该按钮一样。

因此,实际上,对一张图片进行赞成或反对投票就像为所有其他图片点击了该按钮一样。

我知道我正在创建合法的表单,因为我尝试打印表单并将数据返回到控制台。当我这样做时,每个表单都有一个唯一的地址,并且所有表单都在 form.field.data 属性中显示相同的数据(True / False)。 有人可以帮我看看这里发生了什么吗?

表格:

class VoteForm(FlaskForm):
    upvote = SubmitField('vote up')
    downvote = SubmitField('vote down')

路线:

@index_mod.route('/', methods = ['GET', 'POST'])
def index():
    pics = Pic.select().order_by(Pic.score.desc())

    pics_and_forms = []

    for pic in pics:
        voteform = VoteForm()
        #tuple of pic and corresponding form
        pics_and_forms.append( (pic, voteform) )

    for pic, form in pics_and_forms:
        if form.validate_on_submit():
            if form.upvote.data:
                pic.score += 1
                pic.save()
            if form.downvote.data:
                pic.score -= 1
                pic.save()              

    return render_template('index.html', pics_and_forms = pics_and_forms)

神社:

<ul>
    {% for pic, form in pics_and_forms %}
    <li>
        <b>{{ pic.name }}  </b>
        <i>Submitted by {{ pic.user.username }}</i>
        Score: {{ pic.score }}
        <img src="/pic/get/{{ pic.uuid }}" style="width:128px;" >

        <form method="post" action=" {{ url_for('index_mod.index') }}">
        {{ form.csrf_token }}
        {{ form.upvote }}
        {{ form.downvote }}
        </form>

    </li>
    {% endfor %}
</ul>

编辑

所以我发现,虽然我可以在页面上嵌入任意数量的表单,但返回的发布请求并未指定点击了哪个特定表单。

相反,我打算将详细信息嵌入到隐藏字段中,然后使用烧瓶请求对象从隐藏表单中检索该字段。

我宁愿完全使用 Flask-WTF,但似乎没有优雅的方法可以动态地将多个表单添加到页面并检索实际点击的表单。

【问题讨论】:

    标签: python flask wtforms flask-wtforms


    【解决方案1】:

    您一次只提交一个表单,因此您实际上只需要处理一个 Form 对象。我认为更好的方法是将 POST 发布到包含您要投票的 Pic 的 ID 的 URL,然后通过单击的提交按钮捕获赞成/反对票。

    我已经重构了你的代码来说明这一点:

    app.py

    from flask import Flask, render_template, redirect, url_for
    from flask_wtf import FlaskForm
    from wtforms import SubmitField
    
    
    app = Flask(__name__)
    app.secret_key = 'secret'
    
    
    class VoteForm(FlaskForm):
        upvote = SubmitField('vote up')
        downvote = SubmitField('vote down')
    
    
    @app.route("/", methods=['GET'])
    def index():
    
        form = VoteForm()
    
        pics = [
            {
                "name": "test",
                "user": {"username": "test"},
                "score": 1,
                "uuid": 'test'
            },
            {
                "name": "test2",
                "user": {"username": "test"},
                "score": 2,
                "uuid": 'test2'
            }
        ]
    
        return render_template("index.html", form=form, pics=pics)
    
    
    @app.route("/pic/<id>/vote", methods=['POST'])
    def vote(id):
    
        form = VoteForm()
    
        if form.validate_on_submit():
            if form.upvote.data:
                print("Upvote for pic {}".format(id))
            if form.downvote.data:
                print("Downvote for pic {}".format(id))
    
        return redirect(url_for('index'))
    
    
    if __name__ == "__main__":
        app.run(debug=True)
    

    index.html

    <ul>
        {% for pic in pics %}
        <li>
            <b>{{ pic.name }}  </b>
            <i>Submitted by {{ pic.user.username }}</i>
            Score: {{ pic.score }}
            <img src="/pic/get/{{ pic.uuid }}" style="width:128px;" >
    
            <form method="post" action="{{ url_for('vote', id=pic['uuid']) }}">
            {{ form.csrf_token }}
            {{ form.upvote }}
            {{ form.downvote }}
            </form>
    
        </li>
        {% endfor %}
    </ul>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-13
      • 2020-08-27
      • 1970-01-01
      • 1970-01-01
      • 2017-10-12
      相关资源
      最近更新 更多