2011-07-21 9 views
7

Zasadniczo mam ten model, w którym zmapowałem w jednej tabeli klasę "BaseNode" i dwie podklasy. Chodzi o to, że potrzebuję jednej z podklas, aby mieć relację jeden do wielu z drugą podklasą. Tak więc w sortowaniu jest to relacja z innym wierszem innej klasy (podklasy), ale w tej samej tabeli. Jak myślisz, jak mógłbym napisać, używając deklaratywnej składni ?.Relacja SQLAlchemy One-to-Many w dziedziczeniu pojedynczej tabeli - deklaratywna

Uwaga: Z powodu innych relacji w moim modelu, jeśli to możliwe, naprawdę muszę pozostać przy dziedziczeniu z jednego stołu.

class BaseNode(DBBase): 
    __tablename__ = 'base_node' 
    id = Column(Integer, primary_key=True) 
    discriminator = Column('type', String(50)) 
    __mapper_args__ = {'polymorphic_on': discriminator} 

class NodeTypeA(BaseNode): 
    __mapper_args__ = {'polymorphic_identity': 'NodeTypeA'} 
    typeB_children = relationship('NodeTypeB', backref='parent_node') 


class NodeTypeB(BaseNode): 
    __mapper_args__ = {'polymorphic_identity': 'NodeTypeB'} 
    parent_id = Column(Integer, ForeignKey('base_node.id')) 

Stosując ten kod rzuci:

sqlalchemy.exc.ArgumentError: NodeTypeA.typeB_children and back-reference NodeTypeB.parent_node are both of the same direction . Did you mean to set remote_side on the many-to-one side ?

jakieś pomysły lub sugestie?

Odpowiedz

8

Sam się z tym zmagałem wcześniej. Udało mi się dostać to samodzielne referential pracy zależność:

class Employee(Base): 
    __tablename__ = 'employee' 
    id = Column(Integer, primary_key=True) 
    name = Column(String(64), nullable=False) 
Employee.manager_id = Column(Integer, ForeignKey(Employee.id)) 
Employee.manager = relationship(Employee, backref='subordinates', 
    remote_side=Employee.id) 

Należy pamiętać, że manager i manager_id są „monkey-poprawione”, ponieważ nie można zrobić własny odniesień w definicji klasy.

Tak w przykładzie, to myślę, to:

class NodeTypeA(BaseNode): 
    __mapper_args__ = {'polymorphic_identity': 'NodeTypeA'} 
    typeB_children = relationship('NodeTypeB', backref='parent_node', 
     remote_side='NodeTypeB.parent_id') 

EDIT: Zasadniczo co twój błąd jest informacją, jest to, że związek i jego backref są zarówno identyczne. Niezależnie od tego, jakie zasady stosuje SA, aby ustalić, jakie są relacje na poziomie tabeli, nie jive z informacjami, które podajesz.

Dowiedziałem się, że po prostu mówiąc: mycolumn=relationship(OtherTable) w klasie deklaratywnej będzie mycolumn być lista, przy założeniu, że SA może wykryć jednoznaczny związek. Więc jeśli naprawdę chcesz, aby obiekt miał link do jego rodzica, a nie jego dzieci, możesz zdefiniować parent=relationship(OtherTable, backref='children', remote_side=OtherTable.id) w tabeli podrzędnej. To definiuje oba kierunki relacji rodzic-dziecko.

+0

Dziękujemy za szybką odpowiedź !. Próbowałem, ale wciąż mam ten sam błąd. Jak należy zmienić klasę NodeTypeB ?. W kodzie definiujesz Employee.manager_id i Employee.manager poza definicją klasy. Ale w twojej propozycji mojego kodu, nie zrobiłeś tego. Przepraszam, że nie wydaje mi się to jasne. Pozdrawiam. –

+0

Dokumentacja SQLAlchemy mówi, że jest w porządku dostarczanie ciągów, które otrzymują eval'd, dzięki czemu można obejść błąd składni samoodniesienia. Ale nigdy tego nie próbowałem. – wberry

+0

W NodeTypeB twój klucz obcy ma wartość asset_base. Przypuszczam, że to literówka, inaczej zapomniałeś zmienić nazwisko przed opublikowaniem. Myślę, że jeśli zmienisz ForeignKey ("asset_base.id") na ForeignKey (NodeTypeA.id), to będzie blisko mojego przykładu roboczego. – wberry

Powiązane problemy