web-dev-qa-db-ja.com

Flask-SQLAlchemy:行を条件付きで挿入または更新する方法

私のアプリケーションでは、Flask、Flask-SQLAlchemy、Flask-WTF、Jinja2を組み合わせて使用​​しています。

現在の化身には、設定テーブルがあります。テーブルには、1つのフィールドを持つ1つのレコードのみが含まれます。最初、テーブルにはレコードが含まれていません。

私が達成したいのは:

  • Dbにエントリが存在しない場合、ユーザー入力の準備ができている空のフォームを表示します
  • エントリが存在する場合、そのエントリを表示し、
  • ユーザーが値を変更した場合は、データベースのレコードを更新します。

これが私のコードです:

models.py

class Provider(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    rssfeed = db.Column(db.String(120), unique = True)

    def __init__(self, rssfeed):
        self.rssfeed = rssfeed

    def __repr__(self):
        return '<NZBMatrix feed url %r>' % self.rssfeed

forms.py

class SettingsForm(Form):
    rssfeed = TextField('rssfed', validators= [Required()])

views.py

    @app.route('/settings', methods=["GET","POST"])
    def settings():
    """ show settings """
        provider = Provider.query.get(1)
        form = SettingsForm(obj=provider)
        print provider

        if request.method == "POST" and form.validate():
            if Provider.query.get(1) is None:
                provider = Provider(rssfeed=form.rssfeed.data)
                form.populate_obj(provider)
                db.session.add(provider)
                db.session.commit()
                flash("Settings added")

        return render_template("settings.html", form=form)

現状では、このコードはレコードが存在しないがrssfeed列が空の場合にレコードを作成します。

レコードが存在しない場合はINSERT、存在する場合はUPDATEになるように、このコードを変更するにはどうすればよいですか?

18
happygoat

フォームが検証された後など

新しいレコードを追加するには:

new_provider = Provider(form.rssfeed.data)
db.session.add(new_provider)
db.session.commit()

既存のレコードを更新するには:

existing_provider = Provider.query.get(1) # or whatever
# update the rssfeed column
existing_provider.rssfeed = form.rssfeed.data
db.session.commit()

更新の秘訣は、特定のフィールドを変更してコミットするだけでよいということです。残りは、dbセッションによって処理されます。 SQLAlchemyで廃止されたマージ関数を使用していると思います。

31
codegeek

view.pyファイルに次の変更を加えることで問題を解決できました:

@app.route('/settings', methods=["GET","POST"])
def settings():
    """ show settings """
    provider = Provider.query.get(1)
    form = SettingsForm(request.form,obj=provider)

    if request.method == "POST" and form.validate():
        if provider:
            provider.rssfeed = form.rssfeed.data
            db.session.merge(provider)
            db.session.commit()
            flash("Settings changed")
            return redirect(url_for("index"))
        else:
            provider = Provider(form.rssfeed.data)
            db.session.add(provider)
            db.session.commit()
            flash("Settings added")
            return redirect(url_for("index"))
    return render_template("settings.html", form=form)
4
happygoat