0

我一直在学习使用 SQLAlchemy,并试图让它加载数据库中已经存在的数据,通过将元组添加到列表来更改对象的值,然后在数据库中保存/更新它们。

出于某种原因,当我将元组附加到作为元组列表的属性时,SQLAlchemy 的更新程序会忽略它。使用 Session.dirty 并重新查询数据库显示该值没有发生任何变化。

如何创建或更新作为元组列表的对象属性,以便也更新数据库?

这是数据库的代码:

class SQLAlchemyDatabase():

    def __init__(self, DBDirectory, ThisDatabaseName, Report=False):
        ''' Creating the database by path and name given '''

        self.Directory = DBDirectory
        self.DatabaseName = ThisDatabaseName

        # I can't remember why this was in my c++ code...
        # if the new directory should be in another folder,
        # add the backslash, otherwise keep it free of
        # backslashes to make it in the current folder
        if len(self.Directory) > 0:
            self.Directory = self.Directory + "\\"

        DatabasePath = self.Directory + self.DatabaseName

        print "Opening", DatabasePath

        EngineCommand = "sqlite:///"
        self.engine = sqlalchemy.create_engine(EngineCommand+DatabasePath, echo=Report)
        self.Session = sessionmaker(bind=self.engine)
        self.Base = declarative_base()
        try:
            self.DB = self.Session()
        except Error as e:
            print "An error occurred in making the database at", DatabasePath, ":", e.args[0]

        self.Base.metadata.create_all(self.engine)

Statics = SQLAlchemyDatabase("", "Tester.db", True)

这是对象的类代码:

class TestObj(Statics.Base):
    """ Objects that exist as a template for all base objects """
    __tablename__ = "TestObj"

    ID = Column(Text, primary_key=True) 
    ListOfTuples = Column(PickleType, primary_key=False) # List of dual int tuples
    Digit = Column(Integer, primary_key=False)


    def __init__(self,ID, ListOfTuples, Digit):

        # Unique Identifier
        self.ID = ID
        # List of paired int tuples
        self.ListOfTuples = ListOfTuples
        # Some other digit
        self.Digit = Digit

    def __repr__(self, ):
        return "<Material ('%s', '%s', '%s')>" % (self.ID, self.ListOfTuples, self.Digit)

这是我添加、加载、修改然后检查数据库是否更新的代码:

print "Creating each TestObj"
TestObj1 = TestObj("M001", [], 0)
TestObj2 = TestObj("M002", [], 0)
TestObj3 = TestObj("M003", [], 0)

print "Creating the table in the DB"
Statics.Base.metadata.create_all(Statics.engine)
print "Adding each object to the table"
Statics.DB.add(TestObj1)
Statics.DB.add(TestObj2)
Statics.DB.add(TestObj3)

print "Querying the table for the objects"
ListOfObjects = Statics.DB.query(TestObj).all()
print ListOfObjects

print "Modifying the objects to test updating"
NewDigit = 1
for EachObject in ListOfObjects:
    print EachObject
    EachObject.ListOfTuples.append((1,2))
    EachObject.Digit = NewDigit
    NewDigit += 1
    print "Now the Object is:", EachObject

print "Seeing what is to be updated (should show all 3 objects with the ListOfTuples attribute for changing)"
print Statics.DB.dirty

print "Commit changes to DB"
print Statics.DB.commit()

print "Re-query the database to see what the values are now"
ListOfObjects2 = Statics.DB.query(TestObj).all()
print ListOfObjects 
4

1 回答 1

0

作为标量值持久保存到列的 Python 对象和集合,例如作为腌制字符串持久保存的 Python 列表,它们本身不会向 ORM 报告就地更改。要获得这种行为,您必须使用可变扩展自己实现它,您将在其中创建一个报告更改事件的列表子类。

处理标量持久化集合的另一种方法是替换为新集合,而不是原地变异,例如myobject.list_of_tuples = myobject.list_of_tuples + [('new')]. 对列映射属性的分配始终作为更改事件拾取,无需任何额外工作。

于 2013-05-16T04:32:00.730 回答