在实施可变字典时会遇到问题,该字典将对内容的更改做出反应。我已经成功设置SQLAlchemy来管理添加和删除。但是,对存储的dict的内容所做的更改不会“触发” SQLAlchemy数据库的更新。
在这里,我在stackoverflow上发现了其他一些建议:
默认情况下,SQLAlchemy不跟踪dict属性内部的更改。要使其跟踪更改,可以使用可变扩展名:
我在这里How to implement mutable PickleTypes that automatically update on change
但是,我无法正常工作。在我的示例中,当我从Column(PickleType)更改为Column(MutableDict.as_mutable(PickleType))时,SQLAlchemy会话不再找到该对象。下面的代码说明了我正在尝试做的事情。
第一个代码是我设置数据库的地方,第二个代码是我试图向某人添加事务的地方。我设法添加和删除交易,但不更改它们。因此,为什么我尝试使用MutableDict类,但是我似乎并不完全理解它。
设置SQL数据库:(sqlalchemy_declarative.py)
from sqlalchemy import Column, ForeignKey, Integer, String, PickleType
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.mutable import Mutable
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine
Base = declarative_base()
class MutableDict(Mutable, dict):
@classmethod
def coerce(cls, key, value):
if not isinstance(value, MutableDict):
if isinstance(value, dict):
return MutableDict(value)
return Mutable.coerce(key, value)
else:
return value
def __delitem(self, key):
dict.__delitem__(self, key)
self.changed()
def __setitem__(self, key, value):
dict.__setitem__(self, key, value)
self.changed()
def __getstate__(self):
return dict(self)
def __setstate__(self, state):
self.update(self)
class Person(Base):
__tablename__ = 'person_object'
# Here we define columns for the table person
# Notice that each column is also a normal Python instance attribute.
id = Column(Integer, primary_key=True)
first_name = Column(String, nullable=False)
last_name = Column(String, nullable=False)
def __str__(self): # prints when treated as string (for use interface)
return f"Primary id: {self.id} \n" \
f"First name: {self.first_name}"
class Transactions(Base):
__tablename__ = 'transactions'
# Here we define columns for the table address.
# Notice that each column is also a normal Python instance attribute.
id = Column(Integer, primary_key=True)
transactions = Column(MutableDict.as_mutable(PickleType))
# transactions = Column(PickleType)
person_object_id = Column(Integer, ForeignKey('person_object.id'))
person_object = relationship(Person)
def update(self, tmp_dict):
for key, value in tmp_dict.items():
print(key, value)
setattr(self, self.transactions[f'{key}'], value)
def create_db():
# Create an engine that stores data in the local directory's
# sqlalchemy_example.db file.
engine = create_engine('sqlite:///person.db')
# Create all tables in the engine. This is equivalent to "Create Table"
# statements in raw SQL.
Base.metadata.create_all(engine)
示例代码:
from sqlalchemy_declarative import Person, Base, Transactions
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
import sqlalchemy_declarative as sqlalchemy_declarative
def main():
sqlalchemy_declarative.create_db()
engine = create_engine('sqlite:///person.db')
Base.metadata.bind = engine
db_session = sessionmaker()
db_session.bind = engine
session = db_session()
transaction1 = {'item1': 'banana',
'item2': 'apple',
'item3': 'sugar',
'item4': 'coke',
'item5': 'candy'}
transaction2 = {'item1': 'pizza',
'item2': 'water'}
new_obj = Person(first_name='Bob', last_name='Smith')
session.add(new_obj)
new_transaction = Transactions(transactions=transaction1, person_object=new_obj)
session.add(new_transaction)
new_transaction = Transactions(transactions=transaction2, person_object=new_obj)
session.add(new_transaction)
session.commit()
test = session.query(Transactions).all()
for tmp in test:
print(type(tmp.transactions))
print(tmp.transactions == transaction1)
test2 = session.query(Transactions).filter(Transactions.transactions == transaction1).all()
print(test2)
transaction1 = {'item1': 'banana',
'item2': 'apple',
'item3': 'sugar',
'item4': 'coke',
'item5': 'pineapple'}
test2.update(transaction1)
session.commit()
all_transactions = session.query(Transactions).all()
for tmp in all_transactions:
print(tmp.transactions)
if __name__ == '__main__':
main()
但是,test2过滤器找不到与transaction1字典匹配的任何事务。我怀疑这与字典存储为MutableDict而不是Dict的事实有关。但是,我要怎么做,以及添加后如何编辑和更改transaction1。
TLDR:我想更改使用SQLAlchemy存储为ORM的字典中的内容。
答案 0 :(得分:0)
我意识到,不用使用.filter方法就可以解决我的问题。因此,下面的示例可以正常工作。
transaction1 = {'item1': 'banana',
'item2': 'apple',
'item3': 'sugar',
'item4': 'coke',
'item5': 'candy'}
transaction2 = {'item1': 'pizza',
'item2': 'water'}
new_obj = Person(first_name='Bob', last_name='Smith')
session.add(new_obj)
new_transaction = Transactions(transactions=transaction1, person_object=new_obj)
session.add(new_transaction)
new_transaction = Transactions(transactions=transaction2, person_object=new_obj)
session.add(new_transaction)
session.commit()
test = session.query(Transactions).all()
for tmp in test:
print(tmp.transactions)
new_transaction.transactions['item1'] = 'curry banana'
session.commit()
test = session.query(Transactions).all()
for tmp in test:
print(tmp.transactions)