SQLAlchemy无法连接两个表,它们之间有两个外键

时间:2016-09-15 12:36:47

标签: python sqlalchemy

由于Manager类中的这一行owner_id = Column(Integer, ForeignKey('employees.employee_id')),下面的代码无效。 SQLAlchemy生成错误消息:

  

AmbiguousForeignKeysError:无法确定'employees'和>之间的联接“经理人”;表具有多个外键约束关系>它们之间。请明确指定此联接的“onclause”。

请帮忙解决这个问题!

这个想法是每个经理都是员工,并为一些所有者工作。可能有零个,一个或多个经理为业主工作。

from sqlalchemy import (Table, Column, Integer, String, create_engine,
    MetaData, ForeignKey)
from sqlalchemy.orm import mapper, create_session
from sqlalchemy.ext.declarative import declarative_base

e = create_engine('sqlite:////tmp/foo.db', echo=True)
Base = declarative_base(bind=e)

class Employee(Base):
    __tablename__ = 'employees'

    employee_id = Column(Integer, primary_key=True)
    name = Column(String(50))
    type = Column(String(30), nullable=False)

    __mapper_args__ = {'polymorphic_on': type}

    def __init__(self, name):
        self.name = name

class Manager(Employee):
    __tablename__ = 'managers'
    __mapper_args__ = {'polymorphic_identity': 'manager'}

    employee_id = Column(Integer, ForeignKey('employees.employee_id'),
                         primary_key=True)
    manager_data = Column(String(50))

    owner_id = Column(Integer, ForeignKey('employees.employee_id'))


    def __init__(self, name, manager_data):
        super(Manager, self).__init__(name)
        self.manager_data = manager_data

class Owner(Manager):
    __tablename__ = 'owners'
    __mapper_args__ = {'polymorphic_identity': 'owner'}

    employee_id = Column(Integer, ForeignKey('managers.employee_id'),
                         primary_key=True)
    owner_secret = Column(String(50))

    def __init__(self, name, manager_data, owner_secret):
        super(Owner, self).__init__(name, manager_data)
        self.owner_secret = owner_secret

Base.metadata.drop_all()
Base.metadata.create_all()

s = create_session(bind=e, autoflush=True, autocommit=False)    
o = Owner('nosklo', 'mgr001', 'ownerpwd')
s.add(o)
s.commit()

2 个答案:

答案 0 :(得分:2)

SQLAlchemy对如何将Manager加入Employee感到困惑,因为在两个表employee_idowner_id之间有多个外键。在这种情况下,您需要明确指定映射器的inherit_condition

class Manager(Employee):
    __tablename__ = 'managers'

    employee_id = Column(Integer, ForeignKey('employees.employee_id'),
                         primary_key=True)
    manager_data = Column(String(50))

    owner_id = Column(Integer, ForeignKey('employees.employee_id'))

    __mapper_args__ = {'polymorphic_identity': 'manager', 'inherit_condition': employee_id == Employee.employee_id}

答案 1 :(得分:0)

您既可以扩展父模型,也可以定义与同一父模型的关系。

只需使用一种方法,您可以简单地创建关系并让所有模型扩展基类

class Employee(Base):
    __tablename__ = 'employees'

    employee_id = Column(Integer, primary_key=True)
    ...
class Owner(Base):
    __tablename__ = 'owners'
    __mapper_args__ = {'polymorphic_identity': 'owner'}
    owner_id = Column(Integer, primary_key=True)
    ...
    ...
class Manager(Base):
    __tablename__ = 'managers'
    __mapper_args__ = {'polymorphic_identity': 'manager'}

    manager_id = Column(Integer, primary_key=True)
    employee_id = Column(Integer, ForeignKey('employees.employee_id'), primary_key=True)
    owner_id = Column(Integer, ForeignKey('owners.owner_id'))
    ...
    ...

添加其他相关字段,表示为....