【问题标题】:Flask prepopulate form烧瓶预填充表单
【发布时间】:2014-09-08 21:07:20
【问题描述】:

我对烧瓶、烧瓶-wtforms 和烧瓶-sqlalchemy 有一个奇怪的问题。

我有以下表格:

class CompEditForm(Form):

    name = StringField('Company name', validators = [Required()])
    desc = TextAreaField('Description')
    address = StringField('Adress', validators = [Required()])
    ...

    sectors = SelectMultipleField(u'Sectors', coerce=int)
    submit = SubmitField(u'Save changes')

当我编写用于编辑公司的烧瓶视图时:

def edit_company(id):

    comp = Company.query.get_or_404(id)
    form = CompEditForm(request.form,comp)

上面的代码在表单中预先填充了名称、描述等所有字段。由于公司可以在不同的部门开展业务,因此我使用多对多关系对其进行建模。我尝试使用以下内容填充表单的 SelectMultipleFiled:

form.sectors.choices = [(g.id, g.name_srb) for g in Sector.query.order_by('name')]    

到目前为止一切都很好,表格中填充了扇区并且效果很好。这与创建新公司的表格相同。当我希望使用现有扇区预先填充编辑表单时,就会出现问题:

form.sectors.data = [c.id for c in comp.sectors.all()]

它使用正确的扇区填充表单,即它们在呈现时被选中,但是当我提交表单时,它们只是不会更改并匹配用户的输入。它们保持不变:

if form.validate_on_submit():

    print form.sectors.data  # stays the same, not taking account of the user's new choice

有什么想法吗?我尝试使用默认参数而不是数据,但它没有预先填充任何扇区。

【问题讨论】:

    标签: flask flask-sqlalchemy flask-wtforms


    【解决方案1】:

    据我所见,直接初始化数据,wtf Field 的内部丢失了正确对象的跟踪。但是还有另一种初始化字段的方法。初始化时将所需数据直接传递给表单。 Field 的 process 方法将负责初始化其余部分:

    form = CompEditForm(request.form, comp, sectors=[c.id for c in comp.sectors.all()])
    

    【讨论】:

    • 不幸的是,它没有填充表单。
    • 此代码仅用于使选择起作用,在此行之后,您必须按照以前的方式填写选择。实际上,除了删除对 form.sectors.data" 的直接分配并将其添加到 *form 初始化参数之外,我没有更改您的代码中的任何内容。对我来说,它填充了表单,我选择了新用户行业价值。
    【解决方案2】:

    我尝试了 Sadeghi 的解决方案,但正如我所说,它根本没有用初始数据填充表单。最后,我找到了sqlalchemy extension for WTForms,并使用了QuerySelectMultipleField:

    sectors = QuerySelectMultipleField(query_factory=all_sectors, allow_blank=True)
    

    而不是简单的 MultipleSelectField。 all_sectors 工厂是使用>

    定义的简单查询
    def all_sectors():
    
        return Sector.query.all()
    

    然而,提交的表单返回一个查询集对象,而不是通常的名称/ID 组合,因此在用于更新公司数据的代码中我可以简单地说:

    for sec in comp.sectors:            
        comp.sectors.remove(sec)
    
    
    if form.sectors.data:            
        for sek in form.sectors.data:                
            comp.sectors.append(sek)
    

    老实说,我不知道为什么 Sadeghi 的解决方案对我不起作用,我的解决方案更加复杂和丑陋,但它确实有效。谢谢萨德吉。

    【讨论】:

    • 不客气。我认为用你的导入更新你的问题以及你的模型代码和应用初始化(app & db)的导入会有所帮助。那里可能存在一些差异。
    猜你喜欢
    • 2019-02-13
    • 1970-01-01
    • 2018-12-01
    • 2020-12-19
    • 2019-12-01
    • 1970-01-01
    • 2018-01-07
    • 2012-07-20
    • 2017-01-23
    相关资源
    最近更新 更多