यह अन्य घटना आधारित जवाब के साथ-साथ इस प्रकार है, लेकिन मैंने सोचा कि जब से मैं इसे काफी अपने सटीक समस्या को हल करने में लिखा था कि मैं इस कोड पोस्ट करना चाहते हैं,:
कोड (नीचे) एक SessionExtension वर्ग पंजीकृत करता है जो फ्लश के रूप में सभी नई, बदली और हटाई गई वस्तुओं को जमा करता है, फिर सत्र वास्तव में प्रतिबद्ध या वापस घुमाए जाने पर कतार को साफ़ या मूल्यांकन करता है। जिन कक्षाओं में बाहरी फाइल संलग्न है, उनके लिए मैंने obj.after_db_new(session)
, obj.after_db_update(session)
, और/या obj.after_db_delete(session)
विधियों को लागू किया जो सत्र एक्सटेंशन को उचित के रूप में आमंत्रित करता है; फिर आप बाहरी फ़ाइलों को बनाने/सहेजने/हटाने की देखभाल करने के लिए उन विधियों को पॉप्युलेट कर सकते हैं।
नोट: मैं लगभग सकारात्मक हूं कि इसे स्क्लेक्लेमी की नई घटना प्रणाली का उपयोग करके क्लीनर तरीके से फिर से लिखा जा सकता है, और इसमें कुछ अन्य त्रुटियां हैं, लेकिन यह उत्पादन और काम में है, इसलिए मैंने इसे अपडेट नहीं किया है :)
import logging; log = logging.getLogger(__name__)
from sqlalchemy.orm.session import SessionExtension
class TrackerExtension(SessionExtension):
def __init__(self):
self.new = set()
self.deleted = set()
self.dirty = set()
def after_flush(self, session, flush_context):
# NOTE: requires >= SA 0.5
self.new.update(obj for obj in session.new
if hasattr(obj, "after_db_new"))
self.deleted.update(obj for obj in session.deleted
if hasattr(obj, "after_db_delete"))
self.dirty.update(obj for obj in session.dirty
if hasattr(obj, "after_db_update"))
def after_commit(self, session):
# NOTE: this is rather hackneyed, in that it hides errors until
# the end, just so it can commit as many objects as possible.
# FIXME: could integrate this w/ twophase to make everything safer in case the methods fail.
log.debug("after commit: new=%r deleted=%r dirty=%r",
self.new, self.deleted, self.dirty)
ecount = 0
if self.new:
for obj in self.new:
try:
obj.after_db_new(session)
except:
ecount += 1
log.critical("error occurred in after_db_new: obj=%r",
obj, exc_info=True)
self.new.clear()
if self.deleted:
for obj in self.deleted:
try:
obj.after_db_delete(session)
except:
ecount += 1
log.critical("error occurred in after_db_delete: obj=%r",
obj, exc_info=True)
self.deleted.clear()
if self.dirty:
for obj in self.dirty:
try:
obj.after_db_update(session)
except:
ecount += 1
log.critical("error occurred in after_db_update: obj=%r",
obj, exc_info=True)
self.dirty.clear()
if ecount:
raise RuntimeError("%r object error during after_commit() ... "
"see traceback for more" % ecount)
def after_rollback(self, session):
self.new.clear()
self.deleted.clear()
self.dirty.clear()
# then add "extension=TrackerExtension()" to the Session constructor
स्रोत
2012-08-20 14:32:02
इसे * हर * मॉडल * ऐप में * हर * प्रतिबद्धता के लिए कहा जाता है। क्या यह एक ओवरकिल नहीं है? – Devi
क्यों? Deletes सबसे आम ऑपरेशन नहीं हैं और एक समारोह कॉल ज्यादा ओवरहेड नहीं जोड़ता है। – ThiefMaster
लेकिन 'models_committed' केवल 'हटाएं' तक ही सीमित नहीं है, लेकिन 'डालने' और 'अपडेट' के लिए कहा जाता है जो सबसे आम हैं। [डॉक्टर] (https://pythonhosted.org/Flask-SQLAlchemy/signals.html#models_committed) से, "यह सिग्नल भेजा जाता है जब डेटाबेस में प्रतिबद्ध मॉडल बदलते हैं" – Devi