Отношение SQLAlchemy «один ко многим» при наследовании одной таблицы - декларативное - PullRequest
11 голосов
/ 22 июля 2011

По сути, у меня есть эта модель, в которой я сопоставил в одной таблице класс "BaseNode" и два подкласса. Дело в том, что мне нужен один из подклассов, чтобы иметь отношение один ко многим с другим подклассом. Таким образом, это отношения с другой строкой другого класса (подкласса), но в той же таблице. Как вы думаете, я мог бы написать это, используя декларативный синтаксис?.

Примечание: из-за других связей в моей модели, если это возможно, мне действительно нужно придерживаться наследования одной таблицы.

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'))

Используя этот код, вы получите:

sqlalchemy.exc.ArgumentError: NodeTypeA.typeB_children и обратные ссылки NodeTypeB.parent_node имеют одинаковое направление , Вы хотели установить remote_side на сторона много-к-одному?

Есть идеи или предложения?

1 Ответ

12 голосов
/ 22 июля 2011

Я сам переживал это раньше.Мне удалось заставить работать эти самореференциальные отношения:

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)

Обратите внимание, что manager и manager_id "залатаны обезьянами", потому что вы не можете создавать собственные ссылки в определении класса.

Итак, в вашем примере я бы предположил следующее:

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

РЕДАКТИРОВАТЬ : В основном ваша ошибка говорит вам о том, что отношение и его обратная ссылка идентичны.Поэтому, какие бы правила SA ни применял для выяснения отношений на уровне таблицы, они не соответствуют информации, которую вы предоставляете.

Я узнал, что простое высказывание mycolumn=relationship(OtherTable) в вашем декларативном классе приведет кв mycolumn список, предполагая, что SA может обнаружить однозначную связь.Поэтому, если вы действительно хотите, чтобы объект имел ссылку на своего родителя, а не на своих дочерних элементов, вы можете определить parent=relationship(OtherTable, backref='children', remote_side=OtherTable.id) в дочерней таблице.Это определяет оба направления отношений родитель-ребенок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...