WTForms:生成构造函数中的字段

7

由于所需字段的数量可能会有所变化,因此我需要在表单的构造函数中生成我的字段。 我认为我的当前解决方案是有问题的。 当我尝试在模板中扩展表单时,我会收到一个异常,说

AttributeError:'UnboundField'对象没有属性'call'

这段代码有什么问题吗?

class DriverTemplateSchedueForm(Form):
    def __init__(self, per_day=30, **kwargs):
        self.per_day = per_day
        ages = model.Agency.query.all()
        ages = [(a.id, a.name) for a in ages]
        self.days = [[[]] * per_day] * 7
        for d in range(7):
            for i in range(per_day):
                lbl = 'item_' + str(d) + '_' + str(i)
                self.__dict__[lbl] = SelectField(lbl, choices=ages)
                self.days[d][i] = self.__dict__[lbl]
        for day in self.days:
            print(day)

        Form.__init__(self, **kwargs)
2个回答

11

解决方法

您需要将这些字段添加到您的而不是您的实例中:

def driver_template_schedue_form(ages, per_day=30, **kwargs):
    """Dynamically creates a driver's schedule form"""

    # First we create the base form
    # Note that we are not adding any fields to it yet
    class DriverTemplateScheduleForm(Form):
        pass

    # Then we iterate over our ranges
    # and create a select field for each
    # item_{d}_{i} in the set, setting each field
    # *on our **class**.
    for d in range(7):
        for i in range(per_day):
            label = 'item_{:d}_{:d}'.format(d, i)
            field = SelectField(label, choices=ages)
            setattr(DriverTemplateScheduleForm, label, field)

    # Finally, we return the *instance* of the class
    # We could also use a dictionary comprehension and then use
    # `type` instead, if that seemed clearer.  That is:
    # type('DriverTemplateScheduleForm', Form, our_fields)(**kwargs)
    return DriverTemplateScheduleForm(**kwargs)

为什么添加字段到 self 不起作用?

WTForms使用元类将表单和字段注册在一起并保留顺序。 *Field实例是未绑定的,加入到Form类的_unbound_fields属性中,当元类构建类实例时被绑定到类实例上

当运行DriverTemplateScheduleForm.__init__时,_unbound_fields已经被填充。您可以将您的字段推送到self._unbound_fields 中,这样也会正常工作,但这样做是使用私有API,可能会在以后失效。


2
关于元类的答案是正确的,但如果您真的需要这个(就像我一样):
class SomeForm(Form):
    def __init__(self, *args, **kwargs):
        for name in kwargs.keys():
            if name.startswith('PREFIX_'):
                field = HiddenField()
                setattr(self, name, field)
                self._unbound_fields = self._unbound_fields + [[name, field]]
        super(SomeForm, self).__init__(*args, **kwargs)

请注意,我们不会修改_unbound_fields,以便在下一次表单类中不包含这些字段。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接