web-dev-qa-db-ja.com

JSONフィールドの更新がDBに保持されない

ユーザーフラグが挿入されるJSONフィールドを持つモデルがあります。挿入は期待どおりに機能しますが、特定のフラグを削除すると、それらはフィールドに残り、変更はDBに保持されません。

モデルには次のメソッドがあります。

def del_flag(self, key):
    if self.user_flags is None or not key in self.user_flags:
        return False
    else:
        del self.user_flags[key]
        db.session.commit()        
        return True

Databasseはpostgresであり、フィールドタイプにはSQLalchemy JSONフィールドダイアレクトを使用します。これについて何かアドバイスはありますか?

21
trnc

Postgres <9.4を使用している場合、JSONフィールドを直接更新することはできません。 SQLAlchemyへの変更を報告するには、flag_modified関数が必要です。

from sqlalchemy.orm.attributes import flag_modified
model.data['key'] = 'New value'
flag_modified(model, "data")
session.add(model)
session.commit()
28

私の問題は、新しい行を作成するときにSQLAlchemyから返された行オブジェクトを参照することでした。例えばこれ機能しません

_row = db.session.query(SomeTable).filter_by(id=someId).first()
print(row.details)
newDetails = row.details
newDetails['key'] = 'new data'
row.details = newDetails
db.session.commit()
_

新しい辞書を作成する機能します

_row = db.session.query(SomeTable).filter_by(id=someId).first()
print(row.details)
newDetails = dict(row.details)
newDetails['key'] = 'new data'
row.details = newDetails
db.session.commit()
_

注意dict(row.details)

私はJSONフィールドを使用しており、以下のドキュメントを参照しました。

https://docs.sqlalchemy.org/en/13/core/type_basics.html?highlight=json#sqlalchemy.types.JSON

JSON-dictフィールドを変更可能にする方法を示します。 (デフォルトは不変です)

このような..

from sqlalchemy.ext.mutable import MutableDict
from sqlalchemy import Column, Integer, JSON

class TableABC(Base):
    __tablename__ = 'table_abc'
    id = Column(Integer, primary_key=True)
    info = Column(MutableDict.as_mutable(JSON))

次に、jsonフィールドをORMとして更新します。

5
humbledude