2014-04-27 9 views
9

का उपयोग किए बिना संबंध एक-से-कई से सीधे वस्तु हटाएं मैं निम्नलिखित SQLAlchemy सेटअप:SQLAlchemy: session.delete()

Base = declarative_base() 

class Post(Base): 
    __tablename__ = 'post' 
    id = Column(Integer, primary_key=True) 
    title = Column(String(30)) 
    comments = relationship('Comment', cascade='all') 

class Comment(Base): 
    __tablename__ = 'comment' 
    id = Column(Integer, primary_key=True) 
    post_id = Column(Integer, ForeignKey(Post.id, ondelete='CASCADE'), nullable=False) 
    text = Column(Text) 
इस के साथ

, मैं एक एक हैं- साथ पोस्ट वस्तुओं बना सकते हैं टिप्पणियों के साथ कई रिश्ते। मैं सत्र के संदर्भ के बिना पदों के लिए टिप्पणियों के निर्माण और हटाना को संभालना चाहता हूं। एक पोस्ट पर टिप्पणी ठीक काम करता है जोड़ना:

post = Post(title='some post') 
comment = Comment(text='some comment') 
post.comments.append(comment) 

मेरे सत्र हैंडलर केवल पदों के बारे में जानता है, इसलिए यह एक session.add(post) करना होगा और टिप्पणी अपने आप सत्र में रखा जाता है और अगले session.commit() पर डेटाबेस के साथ सिंक्रनाइज़ । हालांकि, टिप्पणियों को हटाने के लिए भी यह सच नहीं है। मैं तो बस ऐसा करके एक टिप्पणी को हटाना सक्षम होना चाहते हैं:

post.comments.remove(comment) 

बहरहाल, यह अगले session.commit() पर निम्न त्रुटि पैदा करता है:

sqlalchemy.exc.OperationalError: (OperationalError) (1048, "Column 'post_id' cannot be null") 'UPDATE comment SET post_id=%s WHERE comment.id = %s' (None, 1L) 

मैं कैसे SQLAlchemy बता साथ टिप्पणी को अद्यतन नहीं करने के लिए करते हैं post_id के लिए NULL मान (जिसे कॉलम पर शून्य बाधा के कारण अनुमति नहीं है), लेकिन इसके बजाय टिप्पणी हटाएं? मुझे पता है कि मैं session.delete(comment) कर सकता था, लेकिन चूंकि मुझे सत्र में टिप्पणी को स्पष्ट रूप से जोड़ने की आवश्यकता नहीं थी, इसलिए मुझे कोई कारण नहीं दिख रहा है कि मुझे इसे सत्र से स्पष्ट रूप से क्यों हटा देना चाहिए।

मुझे संबंधित ऑब्जेक्ट्स को कैस्केडिंग डिलीट के लिए कई समाधान मिलते हैं, लेकिन चूंकि मैंने सत्र में कोई स्पष्ट विलोपन जारी नहीं किया है (पोस्ट अभी भी वहां है), मुझे नहीं लगता कि यह लागू है।

संपादित करें: मैंने पोस्ट से हटाने के कैस्केडिंग को शामिल करने के लिए उदाहरण को समायोजित किया। अब यह session.delete(post) करने के लिए काम करता है और सभी टिप्पणियां हटा दी जाती हैं। लेकिन मैं सिर्फ रिश्तों से हटाई गई टिप्पणियों को स्वचालित रूप से हटाना चाहता हूं और सभी टिप्पणियों के साथ पूरी पोस्ट को हटा नहीं सकता हूं।

टीएल; डीआर: जब मैं एक से कई रिश्ते की रिलेशनशिप सूची से प्रविष्टि हटाता हूं तो मैं एक अद्यतन कथन के बजाय एक डिलीट स्टेटमेंट जारी करने के लिए कैसे कहूं?

उत्तर

5

पढ़ें Configuring delete/delete-orphan Cascade अधिक जानकारी के लिए प्रलेखन की धारा, लेकिन मूल रूप से आप relationship के अपने cascade विकल्प में रूप में अच्छी तरह delete-orphan की जरूरत है:

class Post(Base): 
    # ... 
    comments = relationship('Comment', cascade="all, delete-orphan") 
+0

कैस्केड में 'डिलीट-अनाथ' विकल्प के साथ, रिलेशनशिप सूची से हटाने पर हटाने की अपेक्षा की जाती है। धन्यवाद। – Varicus

0

मैं एक SQLAlchemy उपयोगकर्ता नहीं हूँ, लेकिन मुझे लगता है कि आप ondelete विकल्प

 
    post_id = Column(Integer, ForeignKey(Post.id, ondelete="CASCADE"), nullable=False) 

देखें, MySQL 5.6 मैनुअल 13.6.44, विदेशी कुंजी प्रतिबन्ध

 
SET NULL: Delete or update the row from the parent table, and set the foreign key column or columns in the child table to NULL. 
Both ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported. 
 
CASCADE: Delete or update the row from the parent table, and automatically delete or update the matching rows in the child table. 
Both ON DELETE CASCADE and ON UPDATE CASCADE are supported. Between two tables, do not define several ON UPDATE 
CASCADE clauses that act on the same column in the parent table or in the child table. 

का उपयोग करना चाहिए और http://docs.sqlalchemy.org/en/rel_0_9/core/constraints.html अनुभाग: विदेशी कुंजी परिभाषित करना -> अद्यतन पर और हटाएं

+0

कि शायद जब पद का उपयोग करते हुए 'session.delete (पोस्ट)' को हटाने काम करेगा, लेकिन मैं यह नहीं कर रहा हूँ। इसलिए टिप्पणी करने के लिए कुछ भी नहीं है। मैं सिर्फ टिप्पणी को मिटाना चाहता हूं। – Varicus