【问题标题】:SQLAlchemy can't join two tables with two foreign keys between themSQLAlchemy 不能连接两个表之间有两个外键
【发布时间】:2017-01-23 11:41:31
【问题描述】:

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

AmbiguousForeignKeysError: Can't determine join between 'employees' and > 'managers';表之间有多个外键约束关系。请明确指定此连接的“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()

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    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}
    

    【讨论】:

      【解决方案2】:

      您既要扩展父模型,又要定义与同一个父模型的关系。

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

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

      在指示为 .... 的地方添加其余相关字段。

      【讨论】:

      • 你绝对可以对同一个模型同时拥有继承和关系。
      猜你喜欢
      • 1970-01-01
      • 2019-08-03
      • 1970-01-01
      • 2013-08-06
      • 2015-08-27
      • 1970-01-01
      • 2021-03-08
      • 1970-01-01
      相关资源
      最近更新 更多