2012-07-25 42 views
7

Tôi đang sử dụng SQLAlchemy trong dự án không phải là một ứng dụng web. Nó là một ứng dụng máy chủ tải số lượng các đối tượng khác nhau từ cơ sở dữ liệu và sửa đổi chúng cục bộ, nhưng không muốn lưu các cập nhật đó vào cơ sở dữ liệu mỗi khi một cam kết được ban hành. Trước đây tôi đã làm việc với Django ORM cho một số dự án web và thấy nó phù hợp hơn cho những gì tôi đang cố gắng đạt được. Trong Django ORM tôi có thể .save() mỗi đối tượng bất cứ khi nào tôi muốn mà không lưu những thứ khác tôi có thể không muốn lưu. Tôi hiểu tại sao nó hoạt động như thế này trong SQLAlchemy, nhưng tôi tự hỏi làm thế nào tôi có thể làm điều này theo cách giống như Django?Tắt các thay đổi đối tượng cam kết trong SQLAlchemy


Cập nhật: Để làm cho nó dễ dàng hơn để hiểu những gì tôi đang cố gắng để đạt được, tôi sẽ cung cấp cho bạn một ví dụ.

Đây là cách nó hoạt động thực sự:

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() 

Đây là cách tôi muốn nó hoạt động:

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 

Tôi muốn có kiểm soát tốt hơn về những gì đang thực sự cứu rỗi. Tôi muốn lưu các thay đổi của từng đối tượng cứ 5 phút một lần.

+0

Have a tìm thấy giải pháp của riêng bạn? Nếu bạn có xin vui lòng chia sẻ. –

Trả lời

2

Tôi sử dụng một cái gì đó như:

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() 

và sau đó tôi xác định mô hình của tôi là:

class User(db.Model, BaseModel) 

Vì vậy, bây giờ tôi có thể làm:

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

Đây là những gì bạn đang lên kế hoạch để đạt được?

2

Tôi không chắc tôi hiểu tình trạng khó khăn của bạn.

Trong Django,

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

hoặc cách khác

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

Trong SQLAlchemy,

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

Tại thời điểm này bạn chỉ có thêm các đối tượng để phiên và nó chưa xảy ra cam kết giao dịch. Bạn chỉ cần cam kết sau khi bạn đã thực hiện bất kỳ thay đổi nào được yêu cầu

session.commit() 

hãy xem điều này link. Tôi nghĩ rằng nó sẽ làm cho quá trình chuyển đổi từ Django ORM sang SqlAlchemy dễ dàng hơn.

CẬP NHẬT

Đối với một tình huống như vậy, bạn có thể sử dụng nhiều phiên.

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) 

Tạo bảng 'người dùng' trong db 'kiểm tra'. Ngoài ra, 2 đối tượng phiên, phiên 1 và phiên 2, đã được khởi tạo.

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

Người sử dụng bảng bây giờ sẽ có 2 hồ sơ

1: foo, 10 
2: bar, 20 

Tìm nạp các kỷ lục 'foo' hát session1 và 'bar' sử dụng session2.

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

Làm thay đổi đối với 2 hồ sơ

foo.age = 11 
bar.age = 21 

Bây giờ, nếu bạn muốn thay đổi của foo một mình để thực hiện kết thúc,

session1.commit() 

và cho quầy bar,

session2.commit() 
+0

Tôi đã chỉnh sửa câu hỏi của mình để làm rõ những gì tôi đang cố gắng đạt được. – kjagiello

+0

Tôi sẽ cần một phiên cho mỗi đối tượng tôi sẽ lưu trữ trong ứng dụng của tôi và có vẻ như nó sẽ tạo ra một chi phí khá lớn trong trường hợp của tôi. – kjagiello

0

Không để khuấy động lên một bài cũ, nhưng

Bạn nói:

Tôi muốn lưu các thay đổi của mỗi đối tượng mỗi 5 phút hoặc lâu hơn.

Vậy tại sao không sử dụng một lịch trình như Celery (tôi sử dụng pyramid_celery)

Với điều này bạn có thể tiết kiệm mỗi đối tượng mỗi 5 phút, tức là bạn có thể thêm một trang trí:.

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

này hoạt động tuyệt vời, đặc biệt là khi bạn cần cập nhật cơ sở dữ liệu của bạn để chắc chắn rằng nó được cập nhật (trong trường hợp có nhiều người dùng sử dụng hệ thống của bạn)

Hy vọng điều này sẽ giúp người với, tiết kiệm cứ 5 phút một phần.

Các vấn đề liên quan