使用WTForms,SQLAlchemy&更新记录烧瓶

时间:2018-02-03 00:14:20

标签: python flask sqlalchemy wtforms

每当我使用WTForms编辑表单时,而不是更新记录,它会将其添加为新记录。

我已经在Flaskr示例应用程序中复制了这个,所以它一定是我做错了但我不确定是什么。

我在这里下载了Flaskr:https://github.com/lepture/flask-wtf/tree/master/examples/flaskr

这是一个带有两个输入字段的简单表单 - 标题和文本。可以提交表单,并将条目保存到sqlite数据库。

我尝试修改它以允许更新条目。

class Entry(db.Model):
    __tablename__ = "entries"
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.Unicode(200))
    text = db.Column(db.UnicodeText)

class EntryForm(FlaskForm):
    title = TextField("Title", validators=[DataRequired()])
    text = TextAreaField("Text")
    submit = SubmitField("Share")

@app.route('/add', methods=['POST'])
def add_entry():
    if not session.get('logged_in'):
        abort(401)

    form = EntryForm()
    if form.validate():
        entry = Entry()
        form.populate_obj(entry)
        # entry.id=1
        db.session.add(entry)
        db.session.commit()
        flash('New entry was successfully posted')
    else:
        flash("Your form contained errors")

    return redirect(url_for('show_entries'))

我添加了一个新方法,用现有条目填充表单:

@app.route('/edit/<int:id>', methods=['GET'])
def edit_entry(id=None):
    entries = Entry.query.order_by(Entry.id.asc())
    entry = Entry.query.get(id)
    form = EntryForm(obj=entry)
    return render_template('show_entries.html', entries=entries, form=form)

然后我通过表单添加了一个新条目并导航到http://127.0.0.1:5000/edit/1,它确实用我刚刚创建的条目填充表单。

但是,重新发布表单时,不会更新数据库中的现有记录,而是插入新表单。我想也许是因为ID没有设置在&#39;条目中。对象,但我甚至在保存之前手动将其设置为1,它仍然尝试插入(并且没有PK约束)而不是更新。

2 个答案:

答案 0 :(得分:1)

这是一个古老的问题,但这是我使用Flask-SQLAlchemy的方法。路由是分开的,但是它们都调用同一模板以避免重复。

Form可以将对象作为参数,并填充表单字段以进行“更新”。然后,在表单上调用populate_obj方法来执行此操作,更改对象以反映新的表单字段。现在可以将新实例添加到数据库中。

@app.route("/add_item", methods=['GET', 'POST'])
def add_item():

    form = AddItem()

    if form.validate_on_submit():
        """Get instance of version from form data."""
        item = Item(field1=form.field1.data,
                    field2=form.field2.data,
                    field3=form.field3.data,
                    )
        db.session.add(item)
        db.session.commit()

    return render_template('add_item.html', form=form)


@app.route("/edit_item/<item_id>", methods=['GET', 'POST'])
def edit_item(item_id):

    item = db.session.query(Item).get(item_id)

    form = AddItem(obj=item)
    if form.validate_on_submit():
        form.populate_obj(item)
        db.session.add(item)
        db.session.commit()
        return redirect(url_for('home'))

    return render_template('add_item.html', form=form)

答案 1 :(得分:0)

首先,POST到/ add将始终插入一个新条目,根据您的代码判断。更新和插入应该在不同的端点进行。

SQLAlchemy在后端和数据库之间提供对象关系映射。这意味着,SQLAlchemy不仅会看到您正在制作的新构造的表单与您已插入数据库的表单不同(尽管它们的所有字段都是标识的),但您对此所做的任何更改都是如此。映射对象的字段反映在该对象的数据库条目中。

您只需通过从表中查询对象,将对象的字段设置为更新的值并调用 # Assuming you're using flask-sqlalchemy form = Entry.query.get(id) form.title = 'Fred Flinstone' form.text = 'yabba dabba doo' db.session.commit(form) 即可更新对象。例如:

{{1}}