Reputation: 479
The code below does not work due to this line owner_id = Column(Integer, ForeignKey('employees.employee_id'))
in Manager class. SQLAlchemy generates error message:
AmbiguousForeignKeysError: Can't determine join between 'employees' and > 'managers'; tables have more than one foreign key constraint relationship > between them. Please specify the 'onclause' of this join explicitly.
Please help to fix that!
The idea is that every Manager is an Employee and works for some Owner. There might be zero, one or more Managers working for an Owner.
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()
Upvotes: 3
Views: 5140
Reputation: 20508
SQLAlchemy is confused about how to join Manager
to Employee
because you have multiple foreign keys between the two tables, employee_id
and owner_id
. In this case, you need to specify the inherit_condition
to the mapper explicitly:
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}
Upvotes: 5
Reputation: 54
You are both extending parent model as well as defining relationship to the same parent model.
simply use one way, you could simply created relations and have all your models extend base class
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'))
...
...
add the rest of relevant field where indicated as ....
Upvotes: -1