2012-08-07 13 views
7

के साथ विलोपन व्यवहार यह वास्तव में एक समस्या नहीं है, मैं बस समझना चाहता हूं। निम्नलिखित कोड को ध्यान में रखते:संबंध

from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy import * 
from sqlalchemy.orm import sessionmaker, relationship 
Base = declarative_base() 

class AB(Base): 
    __tablename__= 'ab' 
    id_a = Column(Integer, ForeignKey('a.id', ondelete='CASCADE'), primary_key=True) 
    id_b = Column(Integer, ForeignKey('b.id', ondelete='CASCADE'), primary_key=True) 
    rel = Column(Unicode) 

class A(Base): 
    __tablename__ = 'a' 
    id = Column(Integer, primary_key=True) 

class B(Base): 
    __tablename__ = 'b' 
    id = Column(Integer, primary_key=True) 
    #1: doesn’t work try to set id_b to null 
    rel_a = relationship('AB') 
    # Works, but cascade='all' seems uneeded to me 
    rel_a = relationship('AB', cascade='all') 
    # Works 
    rel_a = relationship('AB', passive_deletes=True) 

engine = create_engine('sqlite://', echo=True) 

import logging 
logger = logging.getLogger('sqlalchemy.engine.base.Engine') 
logger.setLevel(logging.DEBUG) 
handler = logger.handlers[0] 
handler.setLevel(logging.DEBUG) 
handler.setFormatter(logging.Formatter('%(levelname)s %(message)s', '')) 

Base.metadata.create_all(engine) 

sess = sessionmaker(engine)() 

a1 = A() 
b1 = B() 
ab = AB() 

sess.add_all([a1,b1]) 
sess.flush() 

ab.id_a = a1.id 
ab.id_b = b1.id 
ab.rel = u'truite' 
sess.add(ab) 
sess.flush() 
sess.delete(b1) 
sess.flush() 

मैं जब B से संबंधित रिकॉर्ड निकाल दिए जाते हैं AB मेज से रिकॉर्ड हटा दिया जाना चाहते हैं। मैं संबंधों के 3 प्रकार की कोशिश की (बी तालिका में जाँच):

  • 1: काम नहीं करता (AssertionError निर्भरता नियम खाली-आउट प्राथमिक कुंजी स्तंभ उदाहरण पर 'ab.id_b' '' करने की कोशिश की) , जबकि अगर इसे सीधे डेटाबेस में हटाने की कोशिश की जाती है, तो बाधाओं का सही ढंग से उपयोग किया जाता है, और एबी से रिकॉर्ड हटा दिए जाते हैं।

  • 2: काम करता है, मैं ऐसा क्यों की जरूरत है क्योंकि उत्पन्न डेटाबेस समान हैं (आप उत्पादन पर diff जांच कर सकते हैं) नहीं मिलता

  • 3: काम करता है, डीबी की कमी काम करते हैं।

छोड़कर (3) के अलावा, मैं क्यों (2) की जरूरत है नहीं मिलता है, क्योंकि ondelete='cascade' पहले से ही सेट किया गया है, और उत्पन्न डीबी समान है। मेरा अनुमान (1) के साथ होगा, SQLAlchemy के पास सही व्यवहार करने के लिए पर्याप्त जानकारी है।

क्या मुझे कुछ याद आ रही है? धन्यवाद।

+1

इस प्रश्न के लिए आपको बहुत बहुत धन्यवाद। वास्तव में सहायक – clime

उत्तर

10

पर Session संचालन, जैसे Session.delete पर कैस्केड को कॉन्फ़िगर करता है। यह किसी भी ON X CASCADE निर्देशों से स्वतंत्र है जो आपके डेटाबेस में आपकी विदेशी कुंजी बाधाओं पर हो सकते हैं।

आपके मामले में, cascade='all' होने बताता है SQLAlchemy झरना Session.delete पैरेंट ऑब्जेक्ट (AB) बच्चे वस्तु से (अन्य कार्यों के अलावा)। इसके बिना, ऑपरेशन का डिफ़ॉल्ट तरीका न्यूल को विदेशी कुंजी कॉलम में रखना है और संदर्भित ऑब्जेक्ट होना चाहिए।

दूसरी ओर, passive_deletes=TrueON DELETE CASCADE निर्देशों के माध्यम से हटाए गए ऑब्जेक्ट्स को साफ़ करने के लिए डेटाबेस पर भरोसा करने के लिए SQLAlchemy को निर्देश देता है। यह SQLAlchemy को DELETE क्वेरी जारी करने से रोकता है, क्योंकि यह relationship(cascade=...) मामले में करेगा।

+0

यह दस्तावेज़ से अधिक स्पष्ट है, धन्यवाद :) – tonio

+4

क्या यह दस्तावेज़ अनुभाग है जिसे आप पढ़ते हैं? http://docs.sqlalchemy.org/en/rel_0_7/orm/session.html#cascades मैंने उस अनुभाग को कई वर्षों से दर्जनों बार संशोधित किया है, फिर भी और आवश्यकता है? कम से ? इसके बारे में आपको क्या फेंक दिया? – zzzeek

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