Flask-WTF:同一类的多种形式都在提交时返回相同的数据

问题描述 投票:0回答:1

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

然后将此列表传递给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个回答
0
投票

你一次只提交一个表单,所以你真的只需要处理一个Form对象。我认为更好的方法是POST到包含您正在投票的Pic的ID的URL,并从单击的提交按钮捕获上/下投票。

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

app.朋友

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>
© www.soinside.com 2019 - 2024. All rights reserved.