【问题标题】:wtforms, generate fields in constructorwtforms,在构造函数中生成字段
【发布时间】:2015-07-01 12:04:17
【问题描述】:

我需要在表单的构造函数中生成我的字段,因为所需字段的数量可能会有所不同。我认为我目前的解决方案是问题所在。当我尝试在模板中扩展表单时出现异常,说

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)

【问题讨论】:

    标签: python flask wtforms jinja2


    【解决方案1】:

    修复

    您需要将字段添加到您的 class 而不是您的 instance

    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 实例是未绑定创建的,added to the Form class' _unbound_fields attribute 并绑定到类实例 when the class is being constructed by the meta-class

    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,下次不会在表单类中包含此字段。

      【讨论】:

        猜你喜欢
        • 2017-01-23
        • 2019-09-25
        • 2019-11-09
        • 2023-03-15
        • 1970-01-01
        • 1970-01-01
        • 2012-10-02
        • 2016-11-01
        • 2019-09-24
        相关资源
        最近更新 更多