Python 如何使用WTForms从模型列表创建表单?

Python 如何使用WTForms从模型列表创建表单?,python,flask,jinja2,wtforms,flask-wtforms,Python,Flask,Jinja2,Wtforms,Flask Wtforms,我有一个预测模型列表。我想把它们绑定到一个表单上,并允许使用它发回。我如何构建我的表单,以便post将主/客场得分与我绑定到表单的每个项目的预测模型的id字段相关联 查看 @app.route('/predictor/',methods=['GET','POST']) @login_required def predictions(): user_id = g.user.id prediction= # retrieve prediction if request

我有一个
预测
模型列表。我想把它们绑定到一个表单上,并允许使用它发回。我如何构建我的表单,以便post将主/客场得分与我绑定到表单的每个项目的
预测
模型的
id
字段相关联

查看

@app.route('/predictor/',methods=['GET','POST'])
@login_required
def predictions():    
    user_id = g.user.id
    prediction= # retrieve prediction
    if request.method == 'POST':
        if form.validate() == False:
            flash('A score is missing, please fill in all predictions')
            render_template('predictor.html', prediction=prediction, form=form)
        else:
            for pred in prediction:
                # store my prediction
            flash('Prediction added')
            return redirect(url_for("predictions"))    
    # display current predictions
    elif request.method == 'GET':
        return render_template('predictor.html', prediction=prediction, form=form)
表格

class PredictionForm(WTForm):
    id = fields.IntegerField(validators=[validators.required()], widget=HiddenInput())
    home_score = fields.TextField(validators=[validators.required()])
    away_score = fields.TextField(validators=[validators.required()])
模板

  <form action="" method="post">
    {{form.hidden_tag()}}
    <table>
        {% for pred in prediction %}
        <tr>
            <td>{{pred.id}}</td>
            <td>{{form.home_score(size=1)}}</td>
            <td>{{form.away_score(size=1)}}</td>               
        </tr>
        {% endfor %}
    </table>
    <p><input type="submit" value="Submit Predictions"></p>
   </form>

{{form.hidden_tag()}}
{prediction%中的pred为%1}
{{pred.id}
{{form.home_score(size=1)}
{{form.away_score(size=1)}
{%endfor%}


我无法在
POST
上正确绑定数据。所需的验证程序不断失败,因为post数据缺少所有必需的字段。

您需要一个子表单来绑定预测列表中的项目:

您描述的表单只允许您提交一个预测。这似乎存在差异,因为您绑定了一组预测,并且似乎希望每个预测都有一个本地和外地预测。事实上,它不会发回
id
字段。这将始终导致表单验证失败。我认为您需要的是子窗体列表。像这样:

默认情况下,Flask的表单继承自wtforms.ext.SecureForm #这是WTForm基本表单。 从wtforms将表单导入为WTForm #永远不要公开呈现此表单,因为它没有csrf_令牌 班级预测表(WTForm): id=fields.IntegerField(验证器=[validators.required()],widget=HiddenInput()) home\u score=fields.TextField(验证器=[validators.required()])) away\u score=fields.TextField(验证器=[validators.required()])) 类预测列表表单(表单): 预测=字段列表(FormField(PredictionForm)) 您的视图需要返回以下内容:

predictions=#从数据库中获取您的预测列表
从werkzeug.datastructures导入MultiDict
数据={'predictions':预测}
表单=预测列表表单(数据=多目录(数据))
返回呈现模板('predictor.html',form=form)
您的表单需要更改为类似以下内容:


{{form.hidden_tag()}}
{{form.predictions()}}
现在,这将打印每个项目带有
    ,因为FieldList就是这样做的。我将把它留给你来设计样式,并把它做成表格形式。这可能有点棘手,但并非不可能

    在帖子a中,您将获得一个formdata字典,其中包含每个预测的
    id
    的主客场分数。然后可以将这些预测绑定回SQLAlchemy模型

    一些提示,它可能会添加一些导入并清除导入错误消息。

    {%for key in di_RAA%}
    
     {% for key in di_RAA %}
       <tr>
       <td><form id="Run" action="{{ url_for('index') }}" method="post">
            <input type="submit" class="btn" value="TEST" name="RUN_{{key}}"> 
       </form></td>
       </tr>
     {% endfor %}
    
    {%endfor%}
    它为多个按钮提供了其他简单的解决方案。
    FieldList很好,很难获得每个按钮的名称和触发函数。

    我得到了以下错误:UndelinederRor:'wtforms.ext.csrf.fields.CSRFTokenField对象'没有属性'predicts'。在我的视图中,我的预测代码是:predictions=Fixture\u prediction.query.join(Fixture)\.outerjoin(User,Fixture\u prediction.User\u id==User.id)\.Fixture\u id==Fixture.id)\.Fixture\u prediction.User\u id==User\u id.all()看起来它无法找到预测()是否需要对预测进行for循环?我在后面添加了
    hidden_标记
    字段,如果您在Flask中启用了
    CSRF_
    ,这是必需的。这个答案假设您的模型查询工作,并返回一个
    Prediction
    模型列表,其中至少有一个
    id
    字段。如果这个查询不起作用,它就超出了这个问题的范围。还请记住,在您的
    render_模板
    方法中
    form
    必须等于
    PredictionListForm
    而不是
    PredictionForm
    的一个实例,您不需要循环
    字段列表
    遍历每个项目并为每个项目呈现一个
  • 。当然。我真的不能再帮你了。以下是工作要点。可能是您没有包含某些内容,或者是打印错误。我只是复制了您编写的代码,我得到了
      可能与版本有关?可能是我更新了gist,让您比较运行我的gist
      python predictions.py的情况,或者您正在尝试将其集成到您的代码中。因为这就是我想说的,你可能有一些印刷错误或其他不相关的问题。我只是复制了你的代码,并在我的文本编辑器中运行了它。升华文本2
      
      from wtforms import fields
      from wtforms.fields import FieldList, FormField
      from wtforms import validators
      
       {% for key in di_RAA %}
         <tr>
         <td><form id="Run" action="{{ url_for('index') }}" method="post">
              <input type="submit" class="btn" value="TEST" name="RUN_{{key}}"> 
         </form></td>
         </tr>
       {% endfor %}