2013-05-12 9 views
0

我一直在學習使用SQLAlchemy,並試圖讓它加載已經在數據庫中的數據,通過向列表添加元組來更改對象的值,然後保存/在數據庫中更新它們。Python/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 
+0

沒有想法可能會導致此問題?我懷疑它在某種程度上聲明瞭ListOfTuples屬性:ListOfTuples = Column(PickleType,primary_key = False)我認爲我沒有爲SQLAlchemt聲明一個列表,但醃製它似乎是一個正確的方法。 – FacesOfMu 2013-05-14 09:55:36

回答

0

Python對象和集合被持久化爲標量值到一個列,比如一個Python列表,你堅持作爲一個pickle字符串,並不會自己向ORM報告就地更改。爲了得到這種行爲,你必須使用mutable extension來實現你自己,你需要創建一個報告變化事件的列表子類。

另一種處理標量持久化集合的方法是用新的替換,而不是像現有的變化,如myobject.list_of_tuples = myobject.list_of_tuples + [('new')]。對列映射屬性的分配始終作爲更改事件選取,而無需做任何額外的工作。