fields.SelectField可供使用的数据来源不仅可以是预定义的,也可以是从数据库中查询。
tasks = [(r.task_name, r.task_name) for r in db.session.query(Task).all()]
task = fields.SelectField(label=u'发布任务',validators = [validators.required()], choices = tasks)
这样就可以很方便的从数据库中查询到所有的记录,并作为下拉列表框中的选项供使用者选择。
使用SelectField存在的问题
不过严格来说,上述的场景并不是很适合用SelectField。因为在使用过程中会发现即使Task中的数据一直在更新而下拉列表框中的记录永远不变。
主要原因是task是表单类中的一个静态成员,定义之后就保持不变。因此,即使Task表中的数据一直在变,但是tasks的结果是已经固定的。
使用QuerySelectField
解决的办法还是有的,就是使用QuerySelectField,QuerySelectField并不在wtforms.fields文件中,所以导致我们我们并不知道它的存在。而且wtforms的官网也推荐我们
用SelectField支持从数据库中获取记录,导致我们误以为可以那么使用,我忽略了QuerySelectField。
QuerySelectField的使用
from wtforms.ext.sqlalchemy.fields import QuerySelectField
class MyForm(form.Form):
def query_factory():
return [r.name for r in db.session.query(Script).all()]
def get_pk(obj):
return obj
name = QuerySelectField(label=u'脚本名', validators=[validators.required()], query_factory=query_factory, get_pk=get_pk)
QuerySelectField使用起来也是蛮简单的,不过需要提供两个函数,query_factory和get_pk这两个函数。上例中的两个函数是根据我自身使用的场景来使用的,name是Script表的主键。所以,上例中能够动态获取Script表中的主键内容。下拉列表框的内容跟着Script表的数据变化在变化。刚好符合我们的需求。