Использование словаря для вставки полей WTForm. jinja2.exceptions.UndefinedError: «объект wtforms.fields.core.UnboundField» не имеет атрибута «label» - PullRequest
0 голосов
/ 26 апреля 2019

Я пытаюсь заполнить форму в jinja2, используя поля формы, находящиеся в словаре.

#forms.py
class MyForm(FlaskForm):
    name = StringField('New Name', validators=[DataRequired()])

    fields = {}
    fields['Field1'] = StringField('Field 1', validators=[DataRequired()])
    fields['Field2'] = StringField('Field 2', validators=[DataRequired()])

#routes.py
@app.route('/test', methods=['GET', 'POST'])
def test():
    form = MyForm()
    return render_template('_test.html', form=form)

Мой код на Python похож на приведенный выше код.Если я пытаюсь вставить поле name в jinja2, оно работает нормально.

{{ form.name.label(class="form-control-label form-control-sm") }}

Однако я не знаю, как сделать то же самое для поля в словаре fields.Если я использую следующее, это выдает мне ошибку. (jinja2.exceptions.UndefinedError: 'wtforms.fields.core.UnboundField object' has no attribute 'label')

{{ form.fields['Field1'].label(class="form-control-label form-control-sm") }}

Можно ли использовать словарь так, как я пытался его использовать, или есть альтернатива, если у меня многополей.Моя цель при использовании словаря состояла в том, чтобы использовать цикл jinja2 для итерации по элементам словаря, чтобы вставить все поля без ввода одного за другим.

Ответы [ 2 ]

1 голос
/ 26 апреля 2019

Выпуск

WTForms не поддерживает определение полей в атрибуте словаря уровня класса. Базовый класс Form использует FormMeta (из того же файла) в качестве метакласса для идентификации несвязанных полей WTForm в определении класса и связывания их с текущей формой, и это только обнаруживает атрибуты уровня класса.

Решение

Ниже приведен минимальный рабочий пример использования функции фабрики форм.

Дополнительные поля формы передаются в виде лямбда-функции через параметр field_factory, так что мы можем отложить создание дополнительных полей до тех пор, пока не будет создано поле name (хотя любой вызываемый, который возвращает dict, будет работать ). Это необходимо, поскольку WTForms сортирует поля по порядку создания, а не по порядку, указанному в поле items внутри функции make_form().

Затем вы можете отобразить их, выполнив итерацию по форме вместо указания ручного порядка.

Проверено на python 3.7.1.

from flask import Flask
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired

app = Flask(__name__)
app.config['SECRET_KEY'] = "secret"


def make_form(field_factory, name="MyForm"):
    items = dict(name=StringField('New Name', validators=[DataRequired()]),
                 **field_factory())
    my_form = type(name, (FlaskForm,), items)
    return my_form


if __name__ == "__main__":
    with app.test_request_context("/"):
        my_form = make_form(field_factory=lambda: dict(
            Field1=StringField('Field 1', validators=[DataRequired()]),
            Field2=StringField('Field 2', validators=[DataRequired()])
        ))

        form = my_form()
        for field in form:
            print(field())


выход

<input id="name" name="name" required type="text" value="">
<input id="Field1" name="Field1" required type="text" value="">
<input id="Field2" name="Field2" required type="text" value="">
<input id="csrf_token" name="csrf_token" type="hidden" value="IjY5ZWMyNWYxYzg3MzU2MTM1MGMyMTI0OTNiOGY1ZTk4OWFkZWU2Y2Qi.XMNLww.uvari0GZi4weboIecdtv9Vl8Jvg">
0 голосов
/ 26 апреля 2019

Вы не можете сделать это.Поля должны быть определены непосредственно в самой форме.

Но вам это не нужно.Если вы хотите перебирать только поля, вы можете просто сделать это, как показано в документах WTForms .

...