2013-02-10 18 views
11

Tôi có ứng dụng python có nhiều chức năng truy cập cơ sở dữ liệu nhỏ, sử dụng sqlalchemy. Tôi đang cố gắng để tránh có rất nhiều phiên mã boilerplate xử lý xung quanh các chức năng này.Tránh mã xử lý phiên soạn sẵn trong các hàm sqlalchemy

Tôi có rất nhiều chức năng mà giống như thế này:

def get_ticket_history(Session, ticket_id): 
    s = Session() 
    try: 
     rows = s.query(TicketHistory)\ 
       .filter(TicketHistory.ticket_fk==ticket_id)\ 
       .order_by(TicketHistory.id.desc()).all() 
     s.commit() 
     return rows 
    except: 
     s.rollback() 
     raise 
    finally: 
     s.close() 

Tôi cố gắng để cấu trúc lại các chức năng này, nhưng không chắc là tôi có cách tiếp cận tốt nhất được nêu ra. Điều tốt nhất tôi hiện có là:

def execute(Session, fn, *args, **kwargs): 
    s = Session() 
    try: 
     ret = fn(s, *args, **kwargs) 
     s.commit() 
     return ret 
    except: 
     s.rollback() 
     raise 
    finally: 
     s.close() 

def get_ticket_history(self, ticket_id): 
    def sql_fn(s): 
     return s.query(TicketHistory)\ 
       .filter(TicketHistory.ticket_fk==ticket_id)\ 
       .order_by(TicketHistory.id.desc()).all() 
    return execute(self.sentinel_session, sql_fn) 

Có cách nào tốt hơn hoặc thành ngữ hơn để thực hiện việc này không? Có lẽ sử dụng một trang trí?

Cảm ơn, gợi ý Jon

+1

Trình quản lý ngữ cảnh 'sẽ là một cách rất tốt để thực hiện. –

Trả lời

0

morphyn để sử dụng một người quản lý bối cảnh là tốt. Bạn có thể tạo một trình quản lý ngữ cảnh như vậy bằng cách áp dụng trình trang trí contextlib.contextmanager cho một hàm rất giống như get_ticket_history đầu tiên của bạn, thay thế mã giữa try và ngoại trừ câu lệnh yield và đổi tên nó là transaction. PEP 343 có ví dụ gần giống hệt tên đó.

Sau đó, sử dụng trình quản lý ngữ cảnh đó với câu lệnh có để thực hiện lại get_ticket_history. Dường như SQLAlchemy đã cung cấp chức năng đó, tuy nhiên, như phương pháp begin:

http://docs.sqlalchemy.org/en/rel_0_8/orm/session.html#autocommit-mode

14

Các tài liệu SQLAlchemy trình bày một cách có thể làm điều này với các nhà quản lý ngữ cảnh.

http://docs.sqlalchemy.org/en/latest/orm/session_basics.html#when-do-i-construct-a-session-when-do-i-commit-it-and-when-do-i-close-it

Sao chép đoạn mã ở đây cho đầy đủ:

from contextlib import contextmanager 

@contextmanager 
def session_scope(): 
    """Provide a transactional scope around a series of operations.""" 
    session = Session() 
    try: 
     yield session 
     session.commit() 
    except: 
     session.rollback() 
     raise 
    finally: 
     session.close() 

session_scope Điều này có thể được sử dụng sạch sẽ mà không lặp lại những tấm lò bây giờ.

class ThingOne(object): 
    def go(self, session): 
     session.query(FooBar).update({"x": 5}) 

class ThingTwo(object): 
    def go(self, session): 
     session.query(Widget).update({"q": 18}) 

def run_my_program(): 
    with session_scope() as session: 
     ThingOne().go(session) 
     ThingTwo().go(session) 
+10

SQLAlchemy tạo ra một tài liệu có thể, có khả năng và thực hiện đơn giản, giải quyết vấn đề suốt đời của phiên độc đáo. Tại sao họ không đi xa hơn và cung cấp nó như là một chức năng tích hợp thay vì có tất cả người dùng thư viện viết lại một phiên bản của mã đó trong cơ sở mã của họ? – ereOn

+0

Điểm tốt, cũng đã suy nghĩ cùng một điều. –