web-dev-qa-db-fra.com

Les mises à jour du champ JSON ne persistent pas dans la base de données

Nous avons un modèle avec un champ JSON dans lequel les drapeaux utilisateur sont insérés. L'insertion fonctionne comme prévu, mais lors de la suppression de certains indicateurs, ils restent dans le champ et les modifications ne sont pas conservées dans la base de données.

Nous avons la méthode suivante dans notre modèle:

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

La base de données est postgres et nous utilisons le dialecte de champ SQLalchemy JSON pour le type de champ. Un conseil à ce sujet?

21
trnc

Si vous utilisez Postgres <9.4, vous ne pouvez pas mettre à jour le champ JSON directement. Vous avez besoin de la fonction flag_modified pour signaler la modification à SQLAlchemy:

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

Mon problème faisait référence à l'objet de ligne renvoyé par SQLAlchemy lors de la création de la nouvelle ligne. par exemple. cela ne fonctionne pas:

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()

mais créer un nouveau dict ça marche

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()

remarque dict(row.details)

J'utilise le champ JSON et j'ai fait référence au document ci-dessous.

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

Il montre comment rendre le champ JSON-dict mutable. (La valeur par défaut est immuable)

comme ça..

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))

Ensuite, je pourrais mettre à jour le champ json comme ORM.

5
humbledude