我正在玩一个项目管理应用程序。我正在循环项目、项目中的列表以及每个列表中的任务。我希望 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/