Flask-WTF:在validate_on_submit之后,FieldList中的FormField的查询是none

时间:2015-08-17 14:56:33

标签: flask-wtforms

我正在尝试使用Flask-WTF生成动态表单,以基于某些模板创建新产品。产品将根据其类型包含所需键值对的列表,以及构建它所需的部件列表。目前的相关代码如下:

forms.py:

class PartSelectionForm(Form):
    selected_part = QuerySelectField('Part', get_label='serial', allow_blank=True)
    part_type = StringField('Type')
    slot = IntegerField('Slot')
    required = BooleanField('Required')

    def __init__(self, csrf_enabled=False, *args, **kwargs):
        super(PartSelectionForm, self).__init__(csrf_enabled=False, *args, **kwargs)

class NewProductForm(Form):
    serial = StringField('Serial', default='', validators=[DataRequired()])
    notes = TextAreaField('Notes', default='')
    parts = FieldList(FormField(PartSelectionForm))

views.py:

@app.route('/products/new/<prodmodel>', methods=['GET', 'POST'])
@login_required
def new_product(prodmodel):

    try: 
        model = db.session.query(ProdModel).filter(ProdModel.id==prodmodel).one()
    except NoResultFound, e:
        flash('No products of model type -' + prodmodel + '- found.', 'error')
        return redirect(url_for('index'))

    keys = db.session.query(ProdTypeTemplate.prod_info_key).filter(ProdTypeTemplate.prod_type_id==model.prod_type_id)\
        .order_by(ProdTypeTemplate.prod_info_key).all()

    parts_needed = db.session.query(ProdModelTemplate).filter(ProdModelTemplate.prod_model_id==prodmodel)\
        .order_by(ProdModelTemplate.part_type_id, ProdModelTemplate.slot).all()  

    class F(forms.NewProductForm):
        pass   

    for key in keys:
        if key.prod_info_key in ['shipped_os','factory_os']:
            setattr(F, key.prod_info_key, forms.QuerySelectField(key.prod_info_key, get_label='version'))
        else:
            setattr(F, key.prod_info_key, forms.StringField(key.prod_info_key, validators=[forms.DataRequired()]))

    form = F(request.form)

    if request.method == 'GET':
        for part in parts_needed:
            entry = form.parts.append_entry(forms.PartSelectionForm())
            entry.part_type.data=part.part_type_id
            entry.slot.data=slot=part.slot
            entry.required.data=part.required
            entry.selected_part.query = db.session.query(Part).join(PartModel).filter(PartModel.part_type_id==part.part_type_id, Part.status=='inventory')

    if form.__contains__('shipped_os'):
        form.shipped_os.query = db.session.query(OSVersion).order_by(OSVersion.version)
    if form.__contains__('factory_os'):
        form.factory_os.query = db.session.query(OSVersion).order_by(OSVersion.version)

    if form.validate_on_submit():
        ...

在GET请求中,一切都按预期工作,但在validate_on_submit上我得到错误。错误是selected_part列表中QuerySelectField PartSelectionForms的所有查询和query_factories都是none,导致WTForms验证代码中的直接错误或Jinja2尝试重新生成渲染QuerySelectField。我不确定为什么这一切都发生在POST上,当GET的一切看起来都是正确的时候。

1 个答案:

答案 0 :(得分:0)

我意识到虽然我在GET上设置了所需的查询但我没有为POST上的任何PartSelectionForm selected_part条目执行此操作。由于我已将part_typeslotrequired设为隐藏的表单字段,因此我在validate_on_submit之前添加了以下内容,并且一切正常:

for entry in form.parts: 
    entry.selected_part.query = db.session.query(Part).join(PartModel).\
    filter(PartModel.part_type_id==entry.part_type.data, Part.status=='inventory')