2011-05-26 132 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

相關問題