gpt4 book ai didi

python - 使用更改后的 python 字典更新 SQLAlchemy orm 对象

转载 作者:太空宇宙 更新时间:2023-11-03 21:01:40 26 4
gpt4 key购买 nike

在实现对内容变化使用react的可变字典时遇到问题。我已成功设置 SQLAlchemy 来管理添加和删除。但是,对存储的字典内容的更改不会“触发”SQLAlchemy 数据库的更新。

我在 stackoverflow 上发现了一些其他问题,建议:

By default SQLAlchemy doesn't track changes inside dict attributes. To make it track changes, you can use the mutable extension:

我按照这里的例子How to implement mutable PickleTypes that automatically update on change

但是,我无法让它工作。在我的示例中,当我从 Column(PickleType) 更改为 Column(MutableDict.as_mutable(PickleType)) 时,SQLAlchemy session 不再找到该对象。下面的代码说明了我正在尝试做的事情。

第一个代码是我设置数据库的地方,第二个代码是我试图向一个人添加交易的地方。我设法添加交易并删除它们,但无法更改它们。因此,为什么我尝试使用 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 有关。但我该怎么办,以及在添加交易1后如何编辑和更改它。

TLDR:我想更改使用 SQLAlchemy 存储为 ORM 的字典中的内容。

最佳答案

我意识到我可以通过简单地不使用 .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)

关于python - 使用更改后的 python 字典更新 SQLAlchemy orm 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55669649/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com