2013-02-10 69 views
11

मेरे पास एक पाइथन एप्लिकेशन है जिसमें sqlalchemy का उपयोग करके बहुत से छोटे डेटाबेस पहुंच फ़ंक्शन हैं। मैं इन कार्यों के चारों ओर बॉयलरप्लेट सत्र हैंडलिंग कोड रखने से बचने की कोशिश कर रहा हूं।sqlalchemy फ़ंक्शंस में बॉयलरप्लेट सत्र हैंडलिंग कोड से बचें

मैं बहुत से आयोजन कि कुछ इस तरह दिखाई है:

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

मैं इन कार्यों refactor करने के लिए कोशिश कर रहा हूँ, लेकिन यकीन नहीं मैं अभी तक का सबसे अच्छा तरीका है। मेरे पास वर्तमान में सबसे अच्छा है:

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) 

क्या ऐसा करने का बेहतर या अधिक बेवकूफ तरीका है? शायद एक सजावट का उपयोग कर?

धन्यवाद, एक संदर्भ प्रबंधक का उपयोग करने जॉन

+1

एक 'संदर्भ प्रबंधक' जाने का एक बहुत अच्छा तरीका होगा। –

उत्तर

0

morphyn के सुझाव अच्छा है। आप contextlib.contextmanager सजावट को अपने पहले get_ticket_history की तरह फ़ंक्शन में लागू करके, yield कथन के अलावा कोड को प्रतिस्थापित करके और transaction कहकर नाम बदलकर इस तरह के एक संदर्भ प्रबंधक बना सकते हैं। PEP 343 उस नाम का एक करीबी उदाहरण है।

फिर, get_ticket_history को पुन: कार्यान्वित करने के लिए उस कथन प्रबंधक के साथ उस संदर्भ प्रबंधक का उपयोग करें। ऐसा लगता है कि SQLAlchemy पहले से ही, कि समारोह प्रदान करता है की तरह हालांकि, विधि begin के रूप में:

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

14

SQLAlchemy डॉक्स संदर्भ प्रबंधकों के साथ ऐसा करने का एक संभव तरीके से प्रस्तुत करते हैं।

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

संपूर्णता के लिए यहाँ कोड स्निपेट को कॉपी करना:

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 अब बॉयलर प्लेट दोहराए बिना सफाई से किया जा सकता है।

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

एसक्यूएलकेमी दस्तावेज एक संभावित, संभावित और सरल कार्यान्वयन दस्तावेज करता है जो सत्र की आजीवन समस्या को अच्छी तरह से हल करता है। वे अतिरिक्त मील क्यों नहीं गए और सभी लाइब्रेरी उपयोगकर्ता अपने कोड बेस में उस कोड के एक संस्करण को फिर से लिखने के बजाय इसे अंतर्निहित फ़ंक्शन के रूप में प्रदान करते हैं? – ereOn

+0

अच्छा बिंदु, भी वही बात सोच रहा था। –

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^