同一页面上具有相同wtform形式的多个独立实例

时间:2018-12-20 21:58:11

标签: 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 %}

1 个答案:

答案 0 :(得分:2)

您无需创建表单的两个实例,只需将同一实例渲染两次即可。

因此在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魔术的情况下)。