2017-01-13 13 views
2

INSERTのPostgreSQL ON CONFLICT節は、「upsert」機能を提供します(つまり、既存のレコードを更新するか、またはそのようなレコードが存在しない場合は新しいレコードを挿入します)。この機能は、(説明hereなど)PostgreSQLの方言のInsertオブジェクト上on_conflict_do_nothingon_conflict_do_update方法を経由してSQLAlchemyの中でサポートされています。私はあなたのためのSQLAlchemyののエンジン、セッション、および接続を管理flask_sqlalchemyを、使用していますflask_sqlalchemyでPostgreSQLの「INSERT ... ON CONFLICT」(UPSERT)機能を使用するにはどうすればよいですか?

from sqlalchemy.dialects.postgresql import insert 

insert_stmt = insert(my_table).values(
    id='some_existing_id', 
    data='inserted value' 
) 

do_nothing_stmt = insert_stmt.on_conflict_do_nothing(
    index_elements=['id'] 
) 

conn.execute(do_nothing_stmt) 

do_update_stmt = insert_stmt.on_conflict_do_update(
    constraint='pk_my_table', 
    set_=dict(data='updated value') 
) 

conn.execute(do_update_stmt) 

from flask import Flask 
from flask_sqlalchemy import SQLAlchemy 

app = Flask(__name__) 
db = SQLAlchemy(app) 

class MyTable(db.Model): 
    id = db.Column(UUID, primary_key=True) 
    data = db.Column(db.String) 

relation = MyTable(id=1, data='foo') 
db.session.add(relation) 
db.session.commit() 

のでInsertオブジェクトが完全に包まれ、flask_sqlalchemyによって隠されている:データベースに要素を追加するには、私は、このような何かを、私のモデルのインスタンスを作成し、データベースのセッションにそれを追加し、コミット呼び出し。

アップサンプリングを実行するためにPostgreSQL固有の方言メソッドにアクセスするにはどうすればよいですか? flask_sqlalchemyをバイパスして自分のセッションを作成する必要がありますか?私がこれを行うと、どのようにして競合が起こらないようにすることができますか?

答えて

1

db.sessionで下位レベルのステートメントを実行できます。だから、解決策は次のようになります。

from flask import Flask 
from flask_sqlalchemy import SQLAlchemy 
from sqlalchemy.dialects.postgresql import insert as pg_insert 

app = Flask(__name__) 
db = SQLAlchemy(app) 

class MyTable(db.Model): 
    id = db.Column(UUID, primary_key=True) 
    data = db.Column(db.String) 

    def __init__(self, _id, *args, **kwargs): 
     self.id = _id 
     self.data = kwargs['data'] 

    def as_dict(self): 
     return {'id': self.id, 'data': self.data} 

    def props_dict(self): 
     d = self.as_dict() 
     d.pop('id') 
     return d 

relation = MyTable(id=1, data='foo') 
statement = pg_insert(MyTable)\. 
    values(**relation.as_dict()).\ 
    on_conflict_do_update(constraint='id', 
          set_=relation.props_dict()) 

db.session.execute(statement) 
db.session.commit() 

私のモデルクラスでas_dict()props_dict()方法は私が入ってくるHTTPリクエストから不要なプロパティをフィルタリングするためにコンストラクタを使用することができます。

関連する問題