2013-05-12 2 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, но Pickling - это правильный способ сделать это , – FacesOfMu

ответ

0

Объекты и коллекции Python, которые сохраняются как скалярные значения в столбец, такой как список Python, который вы сохраняете как маринованную строку, сами по себе не сообщают об изменениях ORM на месте. Чтобы получить это поведение, это то, что вам нужно реализовать самостоятельно, используя mutable extension, где вы должны создать подкласс списка, который сообщает об изменениях.

Другой способ обработки скалярной коллекции состоит в замене на новую вместо замены на место, например myobject.list_of_tuples = myobject.list_of_tuples + [('new')]. Назначение атрибуту, сопоставляемому с столбцом, всегда воспринимается как событие изменения без дополнительной работы.

Смежные вопросы