假设我有一个项目表和一个任务表。项目可能有许多任务,可以将任务分配给多个项目。我有一个关联表project_task,它有项目和任务之间的映射,还有一个额外的rate
列,用于记录项目特定的任务率。
我如何在Sqlalchemy中映射这种关系?我的目标是project.tasks应该给我一个与项目相关的任务对象列表,task.rate设置为project_task表中记录的速率。
非常感谢!
答案 0 :(得分:2)
在映射中使用表连接:
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.sql import join
from sqlalchemy.orm import relation
from sqlalchemy.orm import column_property
from sqlalchemy.orm import create_session
from sqlalchemy.ext.declarative import declarative_base
engine = sqlalchemy.create_engine('sqlite:///stackoverflow_6144557.db', echo = True)
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))
class Task(Base):
__tablename__ = 'task'
taskid = Column(Integer, primary_key = True)
name = Column(Unicode(255))
description = Column(Text)
rate = Column(DECIMAL(12, 4))
class Project(Base):
__tablename__ = 'project'
projectid = Column(Integer, primary_key = True)
name = Column(Unicode(255))
description = Column(Text)
tasks = relation("ExtendedProjectTask", backref = "project", lazy = 'joined')
class ExtendedProjectTask(Base):
__table__ = join(ProjectTask.__table__, Task.__table__)
projectid = column_property(ProjectTask.projectid)
taskid = column_property(Task.taskid, ProjectTask.taskid)
name = column_property(Task.name)
description = column_property(Task.description)
task_rate = column_property(Task.rate)
project_rate = column_property(ProjectTask.project_rate)
@property
def rate(self):
if self.project_rate is None:
return self.task_rate
else:
return self.project_rate
if __name__ == '__main__':
Base.metadata.create_all(engine)
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)
答案 1 :(得分:0)
这个怎么样?我正在将ProjectTask委托给任务属性的Task。我只设置了一个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)