Как насчет этого? Я делаю ProjectTask делегировать задачу для атрибутов задачи. Я только настраиваю свойство get, но вы можете легко добавлять в set и delete (и вы можете легко придумать, как сделать это в общем).
import sqlalchemy
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import DECIMAL
from sqlalchemy import Unicode
from sqlalchemy import Text
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relation
from sqlalchemy.orm import create_session
from sqlalchemy.ext.declarative import declarative_base
engine = sqlalchemy.create_engine('sqlite:///stackoverflow_6144557.db')
Base = declarative_base(bind=engine)
class ProjectTask(Base):
__tablename__ = 'project_task'
projectid = Column(Integer, ForeignKey('project.projectid'), primary_key=True)
taskid = Column(Integer, ForeignKey('task.taskid'), primary_key=True)
project_rate = Column('rate', DECIMAL(12, 4))
task = relation("Task", backref="project_tasks", lazy="joined")
@property
def name(self):
return self.task.name
@property
def description(self):
return self.task.description
@property
def rate(self):
if self.project_rate is None:
return self.task.rate
else:
return self.project_rate
class Project(Base):
__tablename__ = 'project'
projectid = Column(Integer, primary_key=True)
name = Column(Unicode(255))
description = Column(Text)
tasks = relation(ProjectTask, backref="project", lazy="joined")
class Task(Base):
__tablename__ = 'task'
taskid = Column(Integer, primary_key=True)
name = Column(Unicode(255))
description = Column(Text)
rate = Column(DECIMAL(12, 4))
Base.metadata.create_all(engine)
if __name__ == '__main__':
session = create_session(engine)
for project in session.query(Project).all():
print "\n%r, %r, %r" % (project.projectid, project.name, project.description)
for task in project.tasks:
print "\t%r, %r, %r, %r" % (task.taskid, task.name, task.description, task.rate)