Как создать динамические поля в WTForms

Я пытаюсь создать форму в WTForms с динамическими полями в соответствии с этой документацией http://wtforms.simplecodes.com/docs/1.0.2/specific_problems.html#dynamic-form-composition

У меня есть этот класс подчиненной формы, который позволяет пользователям выбирать товары для покупки из списка:

class Item(Form):
    itmid = SelectField('Item ID')
    qty = IntegerField('Quantity')

class F(Form):
        pass

Будет более одной категории товаров для покупок, поэтому я хотел бы создать поле динамического выбора на основе того, какие категории выберет пользователь:

fld = FieldList(FormField(Item))
fld.append_entry()

но я получаю следующую ошибку:

AttributeError: 'UnboundField' object has no attribute 'append_entry'

Я что-то делаю не так, или в WTForms это невозможно сделать?


person ChiliConSql    schedule 12.10.2012    source источник
comment
Можете ли вы опубликовать больше кода о том, что вы делаете с fld? В идеале это должен быть атрибут класса Form, как в примере в документации: wtforms.simplecodes.com/docs/1.0.2/   -  person aezell    schedule 15.10.2012


Ответы (6)


Я столкнулся с этой проблемой сегодня вечером и закончил с этим. Я надеюсь, что это поможет будущим людям.

RecipeForm.py

class RecipeForm(Form):
    category = SelectField('Category', choices=[], coerce=int)
    ...

просмотры.py

@mod.route('/recipes/create', methods=['POST'])
def validateRecipe():
    categories = [(c.id, c.name) for c in g.user.categories.order_by(Category.name).all()]
    form = RecipeForm(request.form)
    form.category.choices = categories
    ...

@mod.route('/recipes/create', methods=['GET'])
def createRecipe():
    categories = [(c.id, c.name) for c in g.user.categories.order_by(Category.name).all()]
    form = RecipeForm(request.form)
    form.category.choices = categories
    return render_template('recipes/createRecipe.html', form=form)

Я также нашел этот сообщение полезным

person Matt Carrier    schedule 06.05.2013

class BaseForm(Form):
    @classmethod
    def append_field(cls, name, field):
        setattr(cls, name, field)
        return cls

from forms import TestForm
form = TestForm.append_field("do_you_want_fries_with_that",BooleanField('fries'))(obj=db_populate_object)

Я использую расширенный класс BaseForm для всех своих форм и имею удобную функцию append_field для класса.

Возвращает класс с добавленным полем, поскольку экземпляры (полей формы) не могут добавлять поля.

person dza    schedule 19.08.2013
comment
Это изменяет класс формы на месте. Не используйте это для классов, которые являются общими. Вместо этого рассмотрите возможность создания нового подкласса: return type(cls.__name__, (cls,), {name: field}). - person Martijn Pieters; 08.08.2018

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

Вам нужно заполнить choices для SelectField, чтобы увидеть данные и выбрать их. Где вы это заполняете? Первоначальное заполнение должно быть в определении формы, но если вам нравится динамическое, я бы предложил изменить его в том месте, где вы создаете эту форму для показа пользователю. Например, в представлении, где вы выполняете некоторые form = YourForm(), а затем передаете их в шаблон.

Как заполнить поле выбора формы вариантами? У вас должен быть список кортежей, а затем что-то вроде этого:

form.category_select.choices = [(key, categories[key]) for key in categories]
form.category_select.choices.insert(0, ("", "Some default value..."))

categories здесь должен быть словарь, содержащий ваши категории в формате вроде {1:'One', 2:'Two',...}

Поэтому, если вы назначите что-то выбору при определении формы, он будет иметь эти данные с самого начала, и там, где вам нужны пользовательские категории, просто перезапишите их в представлении.

Надеюсь, это натолкнет вас на некоторые идеи, и вы сможете двигаться дальше :)

person Ignas Butėnas    schedule 12.10.2012
comment
Спасибо @ignas-b, но это только заполняет поле «Выбор» значениями, это не устраняет ошибку, которую я получаю. - person ChiliConSql; 12.10.2012
comment
Да ... когда я отправил ответ, я перечитал вопрос и ответ и добавил. Также это может помочь только с заполнением необходимых данных .... :) Ну ладно :) - person Ignas Butėnas; 15.10.2012

Вы пытались вызвать append_entry() в экземпляре формы вместо определения FieldList?

class F(Form)
  fld = FieldList(SelectField(Item))

form = F()
form.fld.append_entry()
person John Ong    schedule 11.09.2014

Вот как я заставил его работать.

class MyForm(FlaskForm):
    mylist = SelectField('Select Field', choices=[])

@app.route("/test", methods=['GET', 'POST']
def testview():
    form = MyForm()
    form.mylist.choices = [(str(i), i) for i in range(9)]

Как ни странно, у меня все это перестает работать, если я использую coerce=int. Я сам flask новичок, поэтому я не совсем уверен, почему coerce=int вызывает проблемы.

person Rohit    schedule 08.01.2019

Документация по WTForms : класс wtforms.fields.SelectField

Выберите поля с динамическими значениями выбора:

class UserDetails(Form):
    group_id = SelectField(u'Group', coerce=int)

def edit_user(request, id):
    user = User.query.get(id)
    form = UserDetails(request.POST, obj=user)
    form.group_id.choices = [(g.id, g.name) for g in Group.query.order_by('name')]
person lfzyx    schedule 17.03.2017