В sqlalchemy, как я могу использовать полиморфное наследование присоединенной таблицы, когда дочерняя таблица имеет несколько внешних ключей к родительской таблице?

у меня есть родительская таблица под названием pbx_point что есть . У меня также есть дочерняя таблица под названием pbx_route, со столбцом под названием point_id указывая на pbx_point.

я хотел бы использовать наследование присоединенной таблицы sqlalchemy для связи этих двух таблиц через декларативную базу и использовать полиморфное наследование

это отлично работает - или, скорее, это было бы, если бы не следующее дополнительное ограничение:pbx_point также имеет внешний ключ, называется initial_route_id указывая к pbx_route.

я также использую отражение ниже, но БД, как я описал выше. Ошибка, которую я получаю, -sqlalchemy.exc.AmbiguousForeignKeysError: Can't determine join between 'pbx_point' and 'pbx_route'; tables have more than one foreign key constraint relationship between them. Please specify the 'onclause' of this join explicitly..

это имеет смысл, так как" за кулисами " delcarative base создает атрибут relationship() для обоих сопоставленных классов. Я бы хотел, чтобы он выбрал pbx_route.point_id как ссылка parent_id, но он также видит . Это было бы просто исправить, если бы я создавал эту связь (), но я не-декларативная система наследования есть.

есть дополнительный аргумент, который я могу передать __mapper_args__, например polymorphic_parent_col что позволит мне указать внешний ключ, который я желаю? Если нет, то как я могу обойти эту проблему?

спасибо.

class MyBase(DeferredReflection):
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()

Base = declarative_base(cls=MyBase)

class pbx_point(Base):
    __mapper_args__ = dict(
        polymorphic_on='point_type',
        with_polymorphic='*',
    )

class pbx_route(pbx_point):
    __mapper_args__ = dict(polymorphic_identity='pbx.route')

это трассировка стека, которую я получаю:

Traceback (most recent call last):
  File "db.py", line 50, in <module>
    Base.prepare(engine)
  File "env/local/lib/python2.7/site-packages/sqlalchemy/ext/declarative/api.py", line 431, in prepare
    thingy.map()
  File "env/local/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 379, in map
    **mapper_args
  File "env/local/lib/python2.7/site-packages/sqlalchemy/orm/__init__.py", line 1147, in mapper
    return Mapper(class_, local_table, *args, **params)
  File "env/local/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 213, in __init__
    self._configure_inheritance()
  File "env/local/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 517, in _configure_inheritance
    self.local_table)
  File "env/local/lib/python2.7/site-packages/sqlalchemy/sql/util.py", line 397, in join_condition
    "join explicitly." % (a.description, b.description))
sqlalchemy.exc.AmbiguousForeignKeysError: Can't determine join between 'pbx_point' and 'pbx_route'; tables have more than one foreign key constraint relationship between them. Please specify the 'onclause' of this join explicitly.

что указывает на то, что он умирает в https://bitbucket.org/sqlalchemy/sqlalchemy/src/7f3494ebad58/lib/sqlalchemy/orm/mapper.py?at=default#cl-517 . Несколько строк выше делает referance к картографу кварг inherit_condition, что, похоже, то, что мне нужно.

1 ответов


ключ inherit_condition аргумент для картографа. Полиморфные информация на самом деле не имеет ничего общего с этим шагом.

исправлены модели:

class MyBase(DeferredReflection):
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()

Base = declarative_base(cls=MyBase)

class pbx_point(Base):
    __mapper_args__ = dict(
        polymorphic_on='point_type',
        with_polymorphic='*',
    )
    id = Column(Integer, primary_key=True)

class pbx_route(pbx_point):
    point_id = Column(Integer, ForeignKey(pbx_point.id))
    __mapper_args__ = dict(
        polymorphic_identity='pbx.route',
        inherit_condition=(point_id == pbx_point.id)
    )

мне нужно добавить id и point_id столбцы, чтобы использовать их в