Wtfforms动态生成 [英] Wtfforms dynamic generation

查看:90
本文介绍了Wtfforms动态生成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个wtfforms

I have two 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)

工作正常,但我想动态生成其中一种表格

It works fine, but I want generate one of this form dynamically

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)

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

If I do so I get an exception on a form validation

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

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

I researched a several questions here with the tags about to wtfforms dynamic generation, but it didn't work for me. What I missed?

推荐答案

导致错误的基本问题是,因为您覆盖了__new__然后调用了超级构造函数,因此您绕过了

the basic issue causing the error is that because you overrode __new__ and then called the super constructor, you consequentially bypassed Form.__init__ which passes a mapping of fields to BaseForm.__init__.

但是,即使尝试符合该界面,也可能最终无法获得所需的东西,除非没有大量的工作.原因是WTForms在Form上使用一个元类,该元类检查字段并在实例化类之前的处缓存未绑定的字段列表,并在实例化时完成输入处理,这需要所有字段到那时已被宣布.

However Even trying to conform this interface probably won't end up getting you what you want, not without a significant amount more work. The reason is that WTForms uses a metaclass on Form which inspects fields and caches the unbound fields list at a point before your class is instantiated, and input processing is done at instantiation time, which requires all fields to have been declared by that point.

遵循解决特定问题中的提示页面上,您可以使用以下方法之一更安全地创建动态表单:

Following the tips from the Solving Specific Problems page, you can more safely create a dynamic form using one of these approaches:

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

1. Presuming SPORTS does not change after application initialization, we can simply create a top-level class and set attributes on it

class SportStartForm(Form):
    pass

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

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

2. alternately, if SPORTS is something that can change and is dynamic due to some user rules, it can be done in-view just like in the above linked page, or as a factory:

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

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

Usage of the factory model could then be something like:

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

这篇关于Wtfforms动态生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆