2011-05-26 131 views
3

假设我有一个项目表和一个任务表。一个项目可能有很多任务,一项任务可能会分配给多个项目。我有一个关联表project_task,它具有项目和任务之间的映射,但还有一个额外的列rate,用于记录项目特定的任务速率。sqlalchemy:保持关联表中的列值为多对多关系

表:项目

  • 专案编号
  • 描述

表:任务

  • 任务id
  • 描述
  • 率< - 违约率

表:Project_Task

  • 专案编号
  • 任务id
  • 率< - 特定项目的速度

我如何将这种关系映射到Sqlalchemy?我的目标是project.tasks应该给我一个与task.rate相关联的任务对象的列表,该列表设置为project_task表中记录的速率。

非常感谢!

回答

1

有一张桌子凑映射:

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) 
0

这个怎么样?我正在将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) 
+0

我想加盟表继承可以更优雅的解决了代表团一行。 – dvincelli 2011-05-30 11:26:24

+0

其实,更值得尝试这里概述的方法:http://www.sqlalchemy.org/docs/06/orm/mapper_config.html#mapping-a-class-against-multiple-tables。我现在正在去上班的路上,但稍后我会再试一试。 – dvincelli 2011-05-30 12:14:51

相关问题