Flask WTF-Alchemy:具有一对多关系的SelectField不会填充

时间:2015-11-02 12:41:47

标签: python flask flask-sqlalchemy wtforms flask-wtforms

我在Scenario(定义项目的特征)和Module(定义太阳能电池板的技术特性)之间有一对多的关系:几个项目可以使用相同的光伏模块。

我已经定义了一些模块,现在我希望能够在Scenario定义页面中选择一个模块。

我可以从我的数据库中提取数据,并可以使用下面的代码正确显示选择字段。

但是,在提交表单时,我收到一个SQL错误:InterfaceError: (sqlite3.InterfaceError) Error binding parameter 0 - probably unsupported type. [SQL: u'UPDATE scenario SET module_id=? WHERE scenario.id = ?'] [parameters: ([], 1)]。看起来我的表单提交了空列表,我不知道该改变什么。

我在SO上发现了一些相关问题,但没有使用WTF Alchemy自动填充字段(我想保留)。

任何帮助将不胜感激!

macros.html

    {% if field.type in ['ModelFieldList', 'QuerySelectField'] %}  
    <div class="control-group">
    <select name="{{field.name}}" class="form-control">
      {% for choice in field.choices %}
        <option value="{{choice.id}}">{{choice.name}}</option>
      {% endfor %}
     </select>
    </div>
    {% else %}
    ...#Other fields 
    {% endif %}

models.py

    class Scenario(db.Model):
        id = db.Column(db.Integer, 
            primary_key=True, 
            autoincrement=True)
        name = db.Column(db.String(140), 
            nullable=False, 
            info={'label': 'Name'})
        module_id = db.Column(db.Integer, 
            db.ForeignKey(Module.id))

        def __repr__(self):
            return '{}'.format(self.name)

    class Module(db.Model):
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        name = db.Column(db.String(140), nullable=False, 
                info={'label': 'Name'},
                 unique=False)
        scenario_list = db.relationship('Scenario', 
            backref=db.relationship('Scenario', backref='module', lazy='dynamic')

        def __repr__(self):
            return '{}'.format(self.name)

forms.py

    ModelForm = model_form_factory(Form)

    class ModuleForm(ModelForm):
        class Meta:
            model = Module

    class ScenarioForm(ModelForm):
        class Meta:
            model = Scenario
        module_id =  ModelFieldList(SelectField(ModuleForm, coerce=int), 
            label= 'Module')

views.py

    @app.route('/scenario/<int:id>/edit', methods=['POST', 'GET'])
    def edit_scenario(id):
        scenario = Scenario.query.get(id)
        form = ScenarioForm()
        if form.validate_on_submit():
            form.populate_obj(scenario)
            db.session.commit()
            flash("{} successfully edited".format(scenario), "success")
            form_action = url_for('scenario', id=id)
            return redirect(form_action)
        form = ScenarioForm(obj=scenario)
        form.module_id.choices = db.session.query(Module.id, Module.name)

        form_title = "Scenario"
        form_action = url_for('edit_scenario', id=id)
        return  render_template('form.html', 
            form = form, 
            form_title = form_title,
            form_action = form_action)

修改 在@dirn回答之后,我做了一些更改:它现在有效,只是我丢失了模块字段的标签。几乎就在那里!

forms.py

    class ScenarioForm(ModelForm):
      class Meta:
        model = Scenario
      module_id =  SelectField(ModuleForm, choices = [(x.id, x.name) for x in db.session.query(Module).all()], coerce=int)

macros.html

  {% if field.type in ['ModelFieldList', 'QuerySelectField', 'SelectField'] %}
  <div class="control-group">
    <select name="{{field.name}}" class="form-control">
      {% for id, name in field.choices %}
        <option value="{{id}}">{{name}}</option>
      {% endfor %}
    </select>
  </div>
  {% else %}
  ...
  {% endif %}

修改 我在没有理解它的情况下从教程中复制粘贴语法,并且我使用SelectField()初始化ModuleForm函数。结果证明它没用,我需要把标签放在那里。

forms.py

    class ScenarioForm(ModelForm):
      class Meta:
        model = Scenario
      module_id =  SelectField('Module', choices = [(x.id, x.name) for x in db.session.query(Module).all()], coerce=int)

0 个答案:

没有答案