python - 同一页面上相同 wtform 表单的多个独立实例

标签 python flask wtforms

我正在玩一个项目管理应用程序。我正在循环项目、项目中的列表以及每个列表中的任务。我希望 CreateTask() 表单出现在任务下方的每个列表中,而且确实如此。

原因是我有 2 个隐藏字段,项目 id 和列表 id。

问题是,虽然表单正确显示,但如果我输入任务名称并提交,它所做的只是刷新页面,并且每个表单都有我在第一个表单中输入的文本。

如何在同一页面的多个实例中使用相同的 WTForms 表单并让它们独立工作?

一个表单,将项目和列表 ID 设置为选择字段,可以正常工作。我可以添加任务。

from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from wtforms import StringField, SelectField, TextAreaField, SubmitField, HiddenField
from wtforms.validators import DataRequired, Length, ValidationError

app = Flask(__name__)
app.config['SECRET_KEY'] = 'f0c4803ba453fc7f8d0c43df21413916'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
db = SQLAlchemy(app)

##################################
######    Database Tables   ######
##################################

class Project(db.Model):
  p_id = db.Column(db.Integer, primary_key=True)
  p_title = db.Column(db.String(300), nullable=False)
  p_list = db.relationship('List', backref="project", lazy=True)
  p_task = db.relationship('Task', backref="project", lazy=True)

  def __repr__(self):
    return f"P('p_id: {self.p_id}','p_title: {self.p_title}','p_list: {self.p_list}', 'p_task: {self.p_task}')" 

class List(db.Model):
  l_id = db.Column(db.Integer, primary_key=True)
  l_title = db.Column(db.String(300), nullable=False)
  l_project = db.Column(db.Integer, db.ForeignKey('project.p_id'), nullable=False)
  l_task = db.relationship('Task', backref="list", lazy=True)

  def __repr__(self):
    return f"L('l_id: {self.l_id}','l_title: {self.l_title}','l_project: {self.l_project}')"

class Task(db.Model):
  t_id = db.Column(db.Integer, primary_key=True)
  t_title = db.Column(db.Integer, nullable=False)
  t_list = db.Column(db.Integer, db.ForeignKey('list.l_id'), nullable=False)
  t_project = db.Column(db.Integer, db.ForeignKey('project.p_id'), nullable=False)

  def __repr__(self):
    return f"T('t_id: {self.t_id}',' t_title: {self.t_title}','t_project: {self.t_project}')"


##################################
#####         Forms         ######
##################################

class CreateTask(FlaskForm):
  project = HiddenField('Project:', validators=[DataRequired()])
  list_select = HiddenField('List:', validators=[DataRequired()])
  task_title = StringField('Task Title:', validators=[DataRequired()])
  submit = SubmitField('Add Task')

##################################
######        Run App       ######
##################################

@app.route('/try', methods=['GET', 'POST'])
def index():
  form = CreateTask(request.values, project="foo", fld2="bar")
  if form.validate_on_submit():
    p_id = form.project.data   
    l_id = form.list_select.data   
    task = form.task_title.data
    new_task = Task(t_project=p_id, t_list=l_id, t_title=task)
    db.session.add(new_task)
    db.session.commit()
  project = Project.query.all()
  return render_template('index.html', form=form, project=project)

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




{% for item in project %}
  <div style="padding: 30px; maring: 30px; border: 1px solid #000;">
    <h2>{{ item.p_title }}</h2><br><hr><br>
    {% for item2 in item.p_list %}
      <h3>{{ item2.l_title }}</h3><br><hr><br>
      {% for item3 in item2.l_task %}
        <h4>{{ item3.t_title }}</h4><br><br>
      {% endfor %}
      <br><br>
      <div style="padding: 40px;">
        <form action="" method="POST">
          {{ form.hidden_tag() }}          
          {{ form.project(value=item.p_id) }}
          {{ form.list_select(value=item2.l_id) }}
          {{ form.task_title.label }}<br>
          {{ form.task_title }}<br><br>
          {{ form.submit }}
        </form>
      </div>
    {% endfor %}
  </div>
{% endfor %}

最佳答案

您不需要创建表单的两个实例,只需渲染同一个实例两次。

所以在 app.py 中它应该是:

def index():
    form1 = CreateTask(request.values, project="foo", fld2="bar")
    form2 = CreateTask(request.values, project="foo", fld2="bar")
    ...
    return render_template('index.html', form1=form1, form2=form2, project=project)

并且模板必须相应更改。如果您想在模板中迭代这两个实例,可以将它们放在一个列表中。

但请注意,如果页面上有多个表单,则只会提交一个表单。如果您想一次编辑多个项目,则需要迭代生成一个表单(至少在不添加一些 JS 魔法的情况下)。

关于python - 同一页面上相同 wtform 表单的多个独立实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53876610/

相关文章:

python - 如何在 jinja2 中获取 WTForms 验证器

python - 使用 Cython 构建部分构建

python - 使用 Psycopg2 插入表 : Do Nothing on Conflict

python - Pandas:如何对重复行的列中的值求和

python - 基于 Flask-Stormpath token 的身份验证

jquery - 通过 wtform 字段获取数据迭代

python - 如何显示 Pymol 中残基之间的距离

python - flask-security:最小化数据库命中

python - peewee.OperationalError : near "AS": syntax error

python - Flask 应用仅在 wtforms 验证后提交目标 ="_blank"表单