1
TLDR;問題は継承の構築にありました。私は宣言的なAPIを使用せずに作成する方法がわかりませんでした。サブクラスのインスタンスをSQLAlchemy関係に配置する
私はDeploymentJob
のようなサブクラスによってさらに絞り込まれる一般的なモデルJob
を作った。各Job
は、複数のActions
で構成されています。このJob<->Action
の関係を定義すると、サブクラスのインスタンスJob
では使用できません。私はDevelopmentJob
を期待
from sqlalchemy import (Table, Binary, Column as C, String, Integer,
ForeignKey, create_engine, MetaData)
from sqlalchemy.orm import (mapper, relationship, backref, scoped_session,
sessionmaker)
metadata = MetaData()
db_engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True)
db_session = scoped_session(sessionmaker(bind=db_engine))
class Job(object):
pass
class DeploymentJob(Job):
def __init__(self, *args, **kwargs):
super(DeploymentJob, self).__init__(*args, **kwargs)
class Action(object):
def __init__(self, unit, job):
self.unit = unit
self.job = job
jobs = Table('jobs', metadata,
C('id', Integer, primary_key=True),
C('type', String, nullable=False)
)
deployment_jobs = Table('deployment_jobs', metadata,
C('id', ForeignKey('jobs.id'), primary_key=True)
)
actions = Table('actions', metadata,
C('job_id', ForeignKey('jobs.id'), primary_key=True),
C('unit', String, primary_key=True)
)
mapper(Job,
jobs,
polymorphic_on=jobs.c.type,
properties = {
'actions': relationship(Action, lazy='dynamic', uselist=True,
backref=backref('job', uselist=False)),
}
)
mapper(DeploymentJob, deployment_jobs, polymorphic_identity='deployment')
mapper(Action, actions)
metadata.create_all(bind=db_engine)
unit = 'second-machine'
job = DeploymentJob()
action = Action(unit, job)
print "action.job -> %s is job: %s" % (action.job, isinstance(action.job, Job))
# >> action.job -> <__main__.DeploymentJob object at 0x7fe> is job: True
db_session.add(action)
db_session.add(job)
db_session.commit()
はJob
インスタンスとして受け入れられているが、この関連付けは行われません。
AssertionError: Attribute 'job' on class '<class '__main__.Action'>' doesn't handle objects of type '<class '__main__.DeploymentJob'>'