2012-07-25 50 views
7

我在不是Web應用程序的項目中使用SQLAlchemy。它是一個服務器應用程序,它從數據庫中加載許多不同的對象並在本地修改它們,但不希望每次發出提交時都將這些更新保存到數據庫中。我以前曾在Django ORM中爲一些Web項目工作,並發現它更適合我嘗試實現的目標。在Django ORM中,我可以每當需要時將每個對象保存(),而不保存其他我可能不想保存的內容。我明白爲什麼它在SQLAlchemy中像這樣工作,但我想知道如何以類似Django的方式執行此操作?在SQLAlchemy中禁用提交對象更改


更新: 爲了更容易理解我想要實現的,我會爲您提供一個例子。

這是它實際上是如何工作的:

a = MyModel.query.get(1) 
b = MyModel.query.get(1) 

a.somefield = 1 
b.somefield = 2 

# this will save both of changed models 
session.commit() 

這是我想要的工作:

a = MyModel.query.get(1) 
b = MyModel.query.get(1) 

a.somefield = 1 
b.somefield = 2 

a.save() 
# I didn't want to save b, changes of b weren't committed 

我想有什麼實際保存更大的控制權。我想每5分鐘左右保存每個對象的更改。

+0

找到了自己的解決方案?如果你有請分享。 – 2012-07-28 06:47:22

回答

2

我使用類似於:

class BaseModel(object): 
    def save(self, commit=True): 
     # this part can be optimized. 
     try: 
      db.session.add(self) 
     except FlushError: 
      # In case of an update operation. 
      pass 

     if commit: 
      db.session.commit() 

    def delete(self, commit=True): 
     db.session.delete(self) 

     if commit: 
      db.session.commit() 

,然後我確定我的模型爲:

class User(db.Model, BaseModel) 

所以,現在我可以這樣做:

u = User(username='foo', password='bar') 
u.save() 

這是你正在計劃實現?

2

我不知道我瞭解你的困境。

在Django中,

foo = MyModel(field1='value1', field2='value2') 
foo.save() 

或可替代

foo = MyModel.objects.create(field1='value1', field2='value2') 

在SQLAlchemy中,

foo = MyModel(field1='value1', field2='value2') 
session.add(foo) 

此時你只添加的對象到會話,它有沒有承諾交易。只有在您完成所需的任何更改之後,您才需要提交。

session.commit() 

請看看這個link。我認爲這會讓從Django ORM到SqlAlchemy的轉換更容易。

UPDATE

對於這樣的情況,您可以使用多個會話。

engine = create_engine("postgresql+psycopg2://user:[email protected]/test") 
metadata = MetaData(bind=engine) 
Session = sessionmaker(bind=engine) 
session1 = Session() 
session2 = Session() 
Base = declarative_base() 
class User(Base): 
    __tablename__ = 'users' 
    id = Column(Integer, primary_key=True) 
    name = Column(String) 
    age = Column(Integer) 
    def __init__(self, name, age): 
     self.name = name 
     self.age = age 
    def __repr__(self): 
     return "<User('%s','%s')>" % (self.name, self.age) 
Base.metadata.create_all(engine) 

在'測試'數據庫中創建一個'用戶'表。另外,2個會話對象session1和session2已經初始化。

a = User('foo','10') 
b = User('bar', '20') 
session1.add(a) 
session1.add(b) 
session1.commit() 

表用戶現在將有2條

1: foo, 10 
2: bar, 20 

抓取的「富」記錄唱會話1和使用工作階段「吧」。

foo = session1.query(User).filter(User.name == "foo").first() 
bar = session2.query(User).filter(User.name == "bar").first() 

進行更改到2條記錄現在

foo.age = 11 
bar.age = 21 

,如果你想獨自foo的變化結轉,

session1.commit() 

和酒吧,

session2.commit() 
+0

我編輯了我的問題,以澄清我想實現的目標。 – kjagiello 2012-07-25 12:05:33

+0

我將需要一個會話每個對象,我將存儲在我的應用程序中,它似乎會在我的情況下會造成相當大的開銷。 – kjagiello 2012-07-30 21:25:21

0

不要給舊的文章,但

你說:

我想保存每個對象的變化,每5分鐘左右。

那麼,爲什麼不使用調度像Celery(我用pyramid_celery

有了這個,你可以節省每個對象,每次5分鐘,即可以添加一個裝飾:

@periodic_task(run_every=crontab(minute="*/5") 
def somefunction(): 
    #your code here 

這特別是當你需要更新你的數據庫,以確保它是最新的(在有許多用戶使用你的系統的情況下)

希望這可以幫助某人與,保存每5分鐘部分。