2011-02-12 4 views
7

나는 일대 다 관계와 두 개의 일대일 관계가 필요한 데이터베이스 모델을 가지고 있습니다. 여기에 내가 만들어 놓은 모델이지만, 그것은 오류 SQLAlchemy에서 여러 개의 자체 참조 관계

class Page(Base): 
    __tablename__ = 'pages' 
    id   = Column(Integer, primary_key=True) 
    title  = Column(String(100), nullable=False) 
    content  = Column(Text, nullable=False) 

    parent_id = Column(Integer, ForeignKey("pages.id"), nullable=True) 
    children = relationship("Page", backref=backref("parent", remote_side=id)) 

    next_id  = Column(Integer, ForeignKey("pages.id"), nullable=True) 
    next  = relationship("Page", backref=backref("prev", remote_side=id, uselist=False)) 

    prev_id  = Column(Integer, ForeignKey("pages.id"), nullable=True) 
    prev  = relationship("Page", backref=backref("next", remote_side=id, uselist=False)) 

    def __init__(self, title, content, parent_id=None, next_id=None, prev_id=None): 
     self.title = title 
     self.content = content 
     self.parent_id = parent_id 
     self.next_id = next_id 
     self.prev_id = prev_id 

    def __repr__(self): 
     return '<Page "%r">' % self.title 

내가 데이터베이스에 무엇을하려고 할 때마다 나는 다음과 같은 오류가

ArgumentError: Could not determine join condition between parent/child tables on relationship Page.children. Specify a 'primaryjoin' expression. If 'secondary' is present, 'secondaryjoin' is needed as well. 

정말로 이상한 것은 그 다음없이 일을한다는 것입니다

을 던지고 및 이전 열. 뭐가 잘못 됐는지 압니까?

답변

14

주제가 오래되었지만 너무 혼란 스럽기 때문에 적어 두겠습니다.
별도의 '이전'열은 필요하지 않으며 이미 '다음'에 대한 역 참조로 사용하고 있습니다. 당신이 동일한 대상에 대한 여러 외래 키를 가지고 있기 때문에 는 또한, 당신은 차를 지정할 필요가 수동으로 조인

class Page(Base): 
    __tablename__ = 'pages' 
    id   = Column(Integer, primary_key=True) 
    title  = Column(String(100), nullable=False) 
    content  = Column(Text, nullable=False) 

    parent_id = Column(Integer, ForeignKey("pages.id"), nullable=True) 
    parent  = relationship("Page", 
        primaryjoin=('pages.c.id==pages.c.parent_id'), 
        remote_side='Page.id', 
        backref=backref("children")) 

    next_id  = Column(Integer, ForeignKey("pages.id"), nullable=True) 
    next  = relationship("Page", 
        primaryjoin=('pages.c.next_id==pages.c.id'), 
        remote_side='Page.id', 
        backref=backref("prev", uselist=False)) 

버그 나 내가 눈치 이상한 행동의 단지 비트의 몇 :
- 당신은 할 수 있습니다 remote_side="Page.id"을 사용하십시오 (remote_side=[id]이 아니라 remote_side=["Page.id"]이 아님). 그렇지 않으면 작동하지 않습니다 (sqlalchemy 0.6.6). 이것은 아래로 고정하는 것을 성가 시게했다.
- 실제 원격 측과 관계없이 항상 기본 키와 함께 remote_side을 사용해야하는 것처럼 보입니다. remote_side="Pages.next_id"은 적절하다고해도 항상 이상한 오류를 생성합니다.
- 별칭을 사용하지 않으므로 primaryjoin 표현이 지옥처럼 혼란 스럽지만 실제로는 올바른 방법입니다. 바인딩 엔진은 매개 변수로 대체 할 표현식을 알고 있습니다 (이는 너무 암시 적이며 Zen, btw에 대한 것입니다).

1

당신은 foreign_keys 사용할 수 있습니다

class Page(Base): 
    __tablename__ = 'pages' 
    id   = Column(Integer, primary_key=True) 
    title  = Column(String(100), nullable=False) 
    content  = Column(Text, nullable=False) 

    parent_id = Column(Integer, ForeignKey("pages.id"), nullable=True) 
    parent  = relationship("Page", 
        foreign_keys=[parent_id], 
        remote_side=[id], 
        backref=backref("children")) 

    next_id  = Column(Integer, ForeignKey("pages.id"), nullable=True) 
    next  = relationship("Page", 
        foreign_keys=[next_id], 
        remote_side=[id], 
        backref=backref("prev", uselist=False))