Wtfforms动态生成 [英] Wtfforms dynamic generation
问题描述
我有两个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__
然后调用了超级构造函数,因此您绕过了 BaseForm.__init__
.
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屋!