从字典中自动填充 wtforms 字段 - 并且能够更改值

问题描述 投票:0回答:1

所以,我有一个 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 字典中的值的正确方法吗 - 如果不是,那是什么?如果我不知道会有多少个字段,如何让字段自动填充 - 我已经研究过字段列表,但这似乎更适合当您有任意数量的关联对象时 - 在这里我们不处理对象而是作为对象成员的字典。任何帮助或指示表示赞赏!

python html flask flask-wtforms wtforms
1个回答
0
投票

您可以使用字典中包含的键动态创建表单,然后通过

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>
© www.soinside.com 2019 - 2024. All rights reserved.