Использование FieldList и FormField

У нас есть следующие формы, и мы пытаемся создать список из GroupRoleForms для каждой группы.

class FullNameMixIn():
    full_name = TextField(
        'Full name', [
            validators.required(message=u"Full name is required")
        ])

class GroupRoleForm(Form):
    group =BooleanField('Group', default=False)
    role = SelectField(
            'Role',choices=[
            ("none", "----------"), 
            ('approver', 'Approver'),
            ('editor', 'Editor')
            ])

class AdminEditUserForm(Form, FullNameMixIn):
    group_roles = FieldList(FormField(GroupRoleForm))

Как мы можем создать экземпляр AdminEditUserForm, содержащий предварительно заполненный список GroupRoleForms?

На данный момент мы пытаемся сделать это так:

form = forms.AdminEditUserForm()
for group in  company.groups:
    group_role_form = forms.GroupRoleForm()
    group_role_form.group.label =  group.name
    group_role_form.group.name = group.id
    form.group_roles.append_entry(group_role_form)
return dict(edit_user_form = form )

person Maeve    schedule 20.08.2012    source источник
comment
Вы когда-нибудь пытались решить эту проблему? если да, опубликуйте свое решение   -  person bool.dev    schedule 23.03.2013
comment
вы хотите, чтобы поля добавлялись динамически? вы знаете, что append_entry не получает данные формы.   -  person dza    schedule 20.08.2013
comment
Просто, добавив функцию инициализации, она сделает именно это.   -  person Games Brainiac    schedule 23.09.2013
comment
Я думаю, ваша динамическая композиция форм может немного переборщить. Вы можете добиться желаемого эффекта, просто привязав свои данные к объекту формы верхнего уровня, позволяя WTForms делать всю работу.   -  person nsfyn55    schedule 30.05.2014
comment
Здесь я создал полный рабочий пример: github.com/sebkouba/dynamic-flask-form < / а>   -  person SebK    schedule 03.01.2016


Ответы (2)


Объяснение

В ваших data или formdata аргументах ключевого слова для Form вам просто нужен словарь с key, который соответствует подполю FieldList, содержащему итерируемый. Элементы в этой итерации, в свою очередь, должны иметь элементы с атрибутами, которые соответствуют списку полей FieldList.

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

Код

from collections import namedtuple

from wtforms import validators
from wtforms import Form
from wtforms import SelectField
from wtforms import BooleanField
from wtforms import TextField
from wtforms import FieldList
from wtforms import FormField

from webob.multidict import MultiDict

# OP's Code
class FullNameMixIn():
    full_name = TextField(
        'Full name', [
            validators.required(message=u"Full name is required")
        ])

class GroupRoleForm(Form):
    group =BooleanField('Group', default=False)
    role = SelectField(
            'Role',choices=[
            ("none", "----------"), 
            ('approver', 'Approver'),
            ('editor', 'Editor')
            ])

class AdminEditUserForm(Form, FullNameMixIn):
    group_roles = FieldList(FormField(GroupRoleForm))

# create some groups
Group = namedtuple('Group', ['group', 'role'])
g1 = Group('group-1', 'none')
g2 = Group('group-2', 'none')

# drop them in a dictionary 
data_in={'group_roles': [g1, g2]}

# Build form 
test_form = AdminEditUserForm(data=MultiDict(data_in))

# test print
print test_form.group_roles()

Визуализированный HTML (усеченный)

<ul id="group_roles">
   <li>
      <label for="group_roles-0">Group Roles-0</label> 
      <table id="group_roles-0">
         <tr>
            <th><label for="gr
               oup_roles-0-group">Group</label></th>
            <td><input checked id="group_roles-0-group" name="group_roles-0-group" type="checkbox" value="y"><
               /td>
         </tr>
         <tr>
            <th><label for="group_roles-0-role">Role</label></th>
            <td>
               <select id="group_roles-0-role" name="group_roles-0-role">
                  <option
                     selected value="none">----------</option>
                  <option value="approver">Approver</option>
                  <option value="editor">Editor</option>
               </select>
            </td
               >
         </tr>
      </table>
   </li>
   <li>
      <label for="group_roles-1">Group Roles-1</label> 
      <table id="group_roles-1">
         <tr>
            <th><label for="group_roles-1-gro
               up">Group</label></th>
            <td><input checked id="group_roles-1-group" name="group_roles-1-group" type="checkbox" value="y"></td>
         </tr>
         <tr>
            <t
               h>
            <label for="group_roles-1-role">Role</label></th>
            <td>
               <select id="group_roles-1-role" name="group_roles-1-role">
                  <option selected value
                     ="none">----------</option>
                  <option value="approver">Approver</option>
                  <option value="editor">Editor</option>
               </select>
            </td>
         </tr>
      </table>
      <
      /li>
</ul>

...
person nsfyn55    schedule 30.05.2014
comment
Достаточно интересно WTForms говорит, что вы не можете использовать логические поля в FieldLists из-за ограничения html, не проверяли ваш образец, но будьте осторожны. - person Drachenfels; 22.05.2015
comment
mreh по-прежнему верно для всех других типов полей. SubmitField не работает по понятным причинам. BooleanField должен завершиться ошибкой при кодировании формы, но это, вероятно, очень незаметно (принимает значение последнего флажка или что-то в этом роде) - person nsfyn55; 22.05.2015
comment
Недавно нашел этот ответ. Исходя из того, что работает для меня, я думаю, что ограничение FieldList в отношении логических полей и полей отправки применяется непосредственно к этим полям, но не к подчиненным формам, включенным в FormField. Также аргумент данных в Form(data=...) не обязательно должен быть MultiDict, подойдет стандартный dict. - person VPfB; 02.01.2017
comment
@VPfB - Это правда. Вы можете просто использовать FieldList(FormField(MyFormWithBooleanFields)), и он отлично работает. - person neil; 06.06.2020

Я не знаком с этими пакетами, но сделаю удар:

class AdminEditUserForm(Form, FullNameMixIn):
    def __init__(self, groups):
        super(AdminEditUserForm, self).__init__()
        self.group_roles = FieldList(FormField(GroupRoleForm))
        for group in groups:
            self.group.label = group.name
            self.group.name = group.id
            self.group_roles.append_entry(self.group)  
            # If this doesn't create a copy of the GroupRoleForm 
            # superclass in group_roles, then you need a method to do it
            self.__clear_group()

    def __clear_group(self):
        # copy GroupRoleForm object, if needed
        # delete GroupRoleForm object
        ...

тогда вы можете назвать это так:

form = forms.AdminEditUserForm(company.groups)
person tenfishsticks    schedule 23.10.2013