2012-08-07 2 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 테이블에서 레코드를 제거해야합니다. 나는 (B 테이블에 확인) 관계의 3 가지 유형을 시도 :

  • 1 : (: 종속성 규칙 빈 아웃 기본 키 열 인스턴스 'ab.id_b' ''을 시도하지 않고 AssertionError가) 작동하지 않습니다 반면 데이터베이스에서 직접 제거하려고하면 제약 조건이 올바르게 사용되고 AB의 레코드가 제거됩니다.

  • 2 : 이것은 생성 된 데이터베이스가 동일하기 때문에 (당신이 출력은 diff를 확인하실 수 있습니다) 필요한 이유 작품, 내가하지 않는

  • 3 : 작품은 DB 제약은 일을. (2) 필요한 이유 ondelete='cascade'가 이미 설정 및 DB가 동일 생성되기 때문에 떠나

(3) 떨어져, 나는하지 않습니다. 내 생각 엔 (1), SQLAlchemy 올바른 정보를 충분한 정보가 있습니다.

내가 누락 된 항목이 있습니까? 감사.

+1

이 질문에 감사드립니다. 정말 도움이되었습니다. – clime

답변

10

cascaderelationshipSession.delete과 같이 Session 연산의 계단식을 구성합니다. 데이터베이스 자체에 외래 키 제약 조건이있을 수있는 ON X CASCADE 지시어와 독립적입니다. cascade='all'을 가진 사용자의 경우

은 SQLAlchemy의이 계단식으로 알려주는 Session.delete 자식 개체에 부모 개체 ( AB)에서 (다른 작업 중). 이를 사용하지 않으면, 디폴트 조작 모드는 외부 키 컬럼에 NULL을 넣고 참조 된 오브젝트를 그대로 두는 것입니다.

한편 passive_deletes=TrueON DELETE CASCADE 지시문을 통해 삭제 된 개체를 정리하기 위해 데이터베이스를 사용하도록 SQLAlchemy에 지시합니다. 이렇게하면 relationship(cascade=...) 경우와 같이 SQLAlchemy가 DELETE 쿼리를 단독으로 발행 할 수 없습니다.

+0

의사보다 명확합니다. :) – tonio

+4

당신이 읽은 문서 섹션은 무엇입니까? http://docs.sqlalchemy.org/ko/rel_0_7/orm/session.html#cascades 수년 동안 수십 번 그 섹션을 수정했지만 여전히 더 많은 것을 필요로합니까? 덜? 너 왜 그 일로 너를 버렸어? – zzzeek

관련 문제