【问题标题】:How do I generate dynamic fields in WTForms如何在 WTForms 中生成动态字段
【发布时间】:2012-10-02 18:28:13
【问题描述】:

我正在尝试根据本文档http://wtforms.simplecodes.com/docs/1.0.2/specific_problems.html#dynamic-form-composition在具有动态字段的 WTForms 中生成一个表单

我有这个子表单类,它允许用户从列表中选择要购买的物品:

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 中实现这一点?

【问题讨论】:

标签: python flask wtforms


【解决方案1】:

在没有编写完整代码或测试代码的情况下发布,但也许它会给你一些想法。此外,这可能仅有助于填充所需的数据。

您需要为SelectField 填写choices 才能看到数据并能够选择它。你在哪里填写?初始填充应该在表单定义中,但如果您喜欢动态填充,我建议您在创建此表单以显示给用户的地方对其进行修改。就像你做一些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',...}

因此,如果您在定义表单时将某些内容分配给选项,它将从一开始就拥有该数据,并且您需要在哪里拥有用户的类别,只需在视图中覆盖它。

希望这会给你一些想法,你可以继续前进:)

【讨论】:

  • 感谢@ignas-b,但这只会用值填充 Select 字段,它不能解决我遇到的错误。
  • 是的...当我发布答案时,我重新阅读了问题和答案并添加了“这可能只有助于填充所需的数据。”... :) 哦,好吧 :)
【解决方案2】:

我今晚遇到了这个问题,最后得到了这个。我希望这对未来的人有所帮助。

RecipeForm.py

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

views.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)

我发现这个post 也很有帮助

【讨论】:

    【解决方案3】:
    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 函数。

    返回附加字段的类,因为(表单字段的)实例不能附加字段。

    【讨论】:

    • 这会修改表单类就地。不要将其用于共享的类。考虑创建一个新的子类:return type(cls.__name__, (cls,), {name: field})
    【解决方案4】:

    您是否尝试过在表单实例上调用 append_entry() 而不是 FieldList 定义?

    class F(Form)
      fld = FieldList(SelectField(Item))
    
    form = F()
    form.fld.append_entry()
    

    【讨论】:

      【解决方案5】:

      WTForms Documentation : class 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')]
      

      【讨论】:

        【解决方案6】:

        这就是我让它工作的方式。

        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 会导致问题。

        【讨论】:

          猜你喜欢
          • 2015-03-05
          • 1970-01-01
          • 1970-01-01
          • 2019-09-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-17
          • 2011-02-22
          相关资源
          最近更新 更多