sqlalchemy: храните значения столбцов из таблицы связей в отношении многие ко многим - PullRequest
3 голосов
/ 27 мая 2011

Предположим, у меня есть таблица проекта и таблица задач.Проект может иметь много задач, и задача может быть назначена нескольким проектам.У меня есть таблица ассоциации project_task, в которой есть сопоставление между проектами и задачами, но также имеется дополнительный столбец rate, который используется для записи частоты задач для конкретного проекта.

Таблица: Проект

  • projectid
  • имя
  • описание

Таблица: Задача

  • taskid
  • имя
  • описание
  • скорость <- скорость по умолчанию </li>

Таблица: Project_Task

  • projectid
  • taskid
  • rate <- специфичная для проекта скорость </li>

Как бы я отобразил эти отношения в Sqlalchemy?Моя цель состоит в том, чтобы project.tasks должен был дать мне список объектов задач, связанных с проектом, для которого task.rate установлен на скорость, записанную в таблице project_task.

Спасибо большое!

Ответы [ 2 ]

2 голосов
/ 30 мая 2011

С объединением таблицы в отображении:

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 голосов
/ 30 мая 2011

Как насчет этого? Я делаю 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...