我想使用WTForms和Jinja2在Flask中创建不同的表单。我调用mysql,它具有字段类型。
因此表格可以是:
form_id | type | key | options | default_value
1 | TextField | title | | test1
1 | SelectField | gender |{'male','female'}|
2 | TextAreaField| text | | Hello, World!
然后我在form_id上查询。然后我想创建一个带有WTforms的表单,其中包含返回的行的字段。
对于普通表格,我这样做:
class MyForm(Form):
title = TextField('test1', [validators.Length(min=4, max=25)])
gender = SelectField('', choices=['male','female'])
def update_form(request):
form = MyForm(request.form)
if request.method == 'POST' and form.validate():
title = form.title.data
gender = form.gender.data
#do some updates with data
return .....
else:
return render_template('template.html',form)
#here should be something like:
#dict = query_mysql()
#new_form = MyForm(dict);
#render_template('template.html',new_form)
我认为最好是创建一个空表单,然后在for循环中添加字段,但是如果表单被回发,如果我没有在类中定义它,我如何验证表单?我在表单中有form_id,因此我可以生成它然后验证。
答案 0 :(得分:6)
我认为最好是创建一个空表单然后在for循环中添加字段,但是如果表单被回发,如果我没有在类中定义它,我如何验证表单?
在实例化表单之前,使用setattr
将字段添加到表单类:
def update_form(request):
table = query()
class MyForm(Form):
pass
for row in table:
setattr(MyForm, row.key, SomeField())
form = MyForm(request.form)
但是,我认为你的问题是一个更大问题的一部分,我试图在下面解决。
你的表似乎很好地映射到表单本身。如果要从表中动态创建表单,可以自己编写逻辑。但是当支持的字段和选项范围增加时,维护可能需要做很多工作。如果您使用的是SQLAlchemy,则可能需要查看WTForms-Alchemy。从其介绍:
很多时候,使用SQLAlchemy构建现代Web应用程序时,您将拥有 与模型紧密贴图的表格。例如,你可能有一个 文章模型,您想要创建一个允许人们发布新内容的表单 文章。在这种情况下,定义字段将是耗时的 您的表单中的类型和基本验证器,因为您已经 定义了模型中的字段。
WTForms-Alchemy提供了一个帮助程序类,可以让您创建一个表单 来自SQLAlchemy模型的类。
帮助程序类是ModelForm
,在表的样式中,下面是使用WTForms-Alchemy的Python 2/3示例。首先安装包wtforms-alchemy
,这也将引入SQLAlchemy和WTForms。
from __future__ import print_function
from __future__ import unicode_literals
import sqlalchemy as sa
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from wtforms_alchemy import ModelForm
engine = create_engine('sqlite:///:memory:')
Base = declarative_base(engine)
Session = sessionmaker(bind=engine)
session = Session()
class MyClass(Base):
__tablename__ = 'mytable'
id = sa.Column(sa.BigInteger, autoincrement=True, primary_key=True)
title = sa.Column(sa.Unicode(5), nullable=False)
gender = sa.Column(sa.Enum('male', 'female', name='gender'))
text = sa.Column(sa.Text)
class MyForm(ModelForm):
class Meta:
model = MyClass
form = MyForm()
print('HTML\n====')
for field in form:
print(field)
运行上面的代码打印:
HTML
====
<input id="title" name="title" required type="text" value="">
<select id="gender" name="gender"><option value="male">male</option><option value="female">female</option></select>
<textarea id="text" name="text"></textarea>
正如你所看到的,WTForms-Alchemy用MyForm
做了很多。该课程基本上是这样的:
class MyForm(Form):
title = StringField(validators=[InputRequired(), Length(max=5)])
gender = SelectField(choices=[('male', 'male'), ('female', 'female')])
text = TextField()
WTForms-Alchemy的文档似乎非常全面。我自己没有用过它,但是如果我有类似的问题需要解决,我肯定会尝试一下。