所以,我有一个 Flask & wtforms 应用程序,其中(为了解释起见)我有人,人有各种属性,但其中之一是字典。键是字符串,值是一个列表,可能有一个或两个字符串,但不能超过。
目前我们在桌子上显示这个字典,但只是纯文本。 html代码是这样的:
{% for item in persons_attributes %}
<tr>
<th scope="row">{{ item.key }}</th>
<td>{{ item.value1 }}</td>
<td>{{ item.value2 }}</td>
</tr>
{% endfor %}
我想让这个表可编辑,我考虑的方式是有一些自动生成的“匿名”字段,由 html 设置。代码看起来像这样
{% for item in persons_attributes %}
<tr>
<th scope="row"><input type="text" name="{{ item.key }}" id="{{ item.key }}" value="{{ item.key }}"></th>
<td><input type="text" name="{{ item.value1 }}" id="{{ item.value1 }}" value="{{ item.value1 }}"></td>
<td><input type="text" name="{{ item.value2 }}" id="{{ item.value2 }}" value="{{ item.value2 }}"></td>
</tr>
{% endfor %}
这有效,就像它将它们呈现为具有正确值的字段一样 - 但是我无法在其他地方访问它们,大概是因为我实际上在 wtforms 中没有任何与它们关联的字段? form.data(其中 form 是我的表单)未显示这些字段 - 其他显示正常,但不是这些
所以,是的,我想我的问题是 - 这是使用 wtforms 编辑存储在 Flask 字典中的值的正确方法吗 - 如果不是,那是什么?如果我不知道会有多少个字段,如何让字段自动填充 - 我已经研究过字段列表,但这似乎更适合当您有任意数量的关联对象时 - 在这里我们不处理对象而是作为对象成员的字典。任何帮助或指示表示赞赏!
您可以使用字典中包含的键动态创建表单,然后通过
data
属性将值传输到此表单。
以下示例通过迭代字典的键并为每个键添加表单字段来创建表单。 创建表单后,将通过
data
属性 填充字典中的值,然后显示。from flask import (
Flask,
render_template,
request
)
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired
app = Flask(__name__)
app.secret_key = 'your secret here'
class PersonForm(FlaskForm):
pass
def form_factory(keys):
class F(PersonForm):
pass
for key in keys:
field = StringField(key, [DataRequired()])
setattr(F, f'attr-{key}', field)
return F
@app.route('/edit', methods=['GET', 'POST'])
def edit():
person = {
'key': 'key-value',
'value1': 'value1-value',
'value2': 'value2-value'
}
form = form_factory(person.keys())(request.form, data=person)
if form.validate_on_submit():
for key in person.keys():
field = getattr(form, f'attr-{key}')
person[key] = field.data
print(person)
return render_template('edit.html', **locals())
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Edit</title>
</head>
<body>
<form method="post">
{{ form.csrf_token }}
{% for field in form -%}
{% if field.widget.input_type != 'hidden' -%}
<div>
{{ field.label() }}
{{ field() }}
{% if field.errors -%}
<ul>
{% for error in field.errors -%}
<li>{{ error }}</li>
{% endfor -%}
</ul>
{% endif -%}
</div>
{% endif -%}
{% endfor -%}
<button type="submit">Submit</button>
</form>
</body>
</html>