【问题标题】:Wtfforms dynamic generationWtforms 动态生成
【发布时间】:2016-01-04 03:40:44
【问题描述】:

我有两个 wtfforms

class SportStartForm(Form):
    ski = DateField(format='%d.%m.%Y')
    kitesurfing = DateField(format='%d.%m.%Y')
    windsurfing = DateField(format='%d.%m.%Y')
    surfing = DateField(format='%d.%m.%Y')


class UpdateUserForm(Form):
    sport_start_at = FormField(SportStartForm)

它工作正常,但我想动态生成这种形式之一

class SportStartForm(Form):
    def __new__(cls, **kwargs):
       for s in SPORTS:
           setattr(cls, s, DateField(format='%d.%m.%Y'))
    return super(SportStartForm, cls).__new__(cls, **kwargs)

如果我这样做,我会在表单验证中遇到异常

for name, unbound_field in itertools.chain(fields, extra_fields):
TypeError: 'NoneType' object is not iterable

我在这里研究了几个关于 wtfforms 动态生成的标签的问题,但它对我不起作用。我错过了什么?

【问题讨论】:

    标签: python wtforms flask-wtforms


    【解决方案1】:

    导致错误的基本问题是,因为您覆盖了__new__,然后调用了超级构造函数,因此您绕过了Form.__init__,它将字段映射传递给BaseForm.__init__

    然而即使尝试遵循这个接口也可能不会最终得到你想要的东西,而不是没有大量的工作。原因是 WTForms 在 Form 上使用了一个元类,它检查字段并在您的类实例化之前 缓存未绑定的字段列表,并且输入处理在实例化时完成,这需要所有字段到那时就已经宣布了。


    按照Solving Specific Problems 页面中的提示,您可以使用以下方法之一更安全地创建动态表单:

    1.假设SPORTS在应用程序初始化后不会改变,我们可以简单地创建一个顶级类并在其上设置属性

    class SportStartForm(Form):
        pass
    
    for s in SPORTS:
        setattr(SportStartForm, s, DateField(format='%d.%m.%Y'))
    

    2. 或者,如果 SPORTS 由于某些用户规则而可以改变并且是动态的,则可以像在上面链接的页面中一样在视图中完成,或者作为工厂:

    def factory(sports):
        # This form class is created in a local scope, so a new class object
        # is made each time your factory is called
        class SportStartForm(Form):
            pass
    
        for s in sports:
            setattr(SportStartForm, s, DateField(format='%d.%m.%Y'))
    
        return SportStartForm
    

    工厂模型的使用可能类似于:

    def view(request):
        form_class = factory(['tennis', 'golf', 'windsurfing'])
        form = form_class(request.form)
        # etc, rest of view
    

    【讨论】:

      猜你喜欢
      • 2015-03-05
      • 2012-10-02
      • 1970-01-01
      • 2019-07-23
      • 1970-01-01
      • 1970-01-01
      • 2020-01-18
      • 2021-03-04
      • 2018-04-05
      相关资源
      最近更新 更多