2014-09-02 61 views
0

我試圖創建一個簡單的樹結構的任務。任務可以有一個狀態(done:boolean)和一個標題(title:string)以及任意數量的子任務(任務:Task [])。我成功地設法創建了一個Task對象和關聯代理對象PositionedTask。父母/子女關係似乎有效,儘管定位未被使用。SQLAlchemy使用關聯代理對象進行排序的樹結構定位

這是迄今爲止我已經得到了代碼:

import sys 

from sqlalchemy import Column 
from sqlalchemy import Integer 
from sqlalchemy import String 
from sqlalchemy import Boolean 
from sqlalchemy import ForeignKey 
from sqlalchemy.orm import relationship 
from sqlalchemy.orm import backref 
from sqlalchemy.orm import Session 
from sqlalchemy.ext.associationproxy import association_proxy 
from sqlalchemy.ext.orderinglist import ordering_list 

from sqlalchemy import create_engine 
from sqlalchemy.ext.declarative import declarative_base 


Base = declarative_base() 


class Task(Base): 
    __tablename__ = 'tasks' 

    id = Column(Integer, primary_key=True) 
    title = Column(String, nullable=False) 
    done = Column(Boolean, nullable=True, default=False) 

    parent_id = Column(Integer, ForeignKey('tasks.id')) 
    tasks = association_proxy('tasks_positioned', 'task') 

    def __init__(self, title=None, done=False): 
     self.title = title 
     self.done = done 

    def __repr__(self): 
     return '<Task #{0} \'{1}\' done={2}>'.format(self.id, self.title, self.done) 



class PositionedTask(Base): 
    __tablename__ = 'tasks_subtasks' 
    parent_id = Column(Integer, ForeignKey('tasks.id'), primary_key=True) 
    task_id = Column(Integer, ForeignKey('tasks.id'), primary_key=True) 
    position = Column(Integer, default=0, nullable=False) 

    parent = relationship(Task, foreign_keys='PositionedTask.parent_id', backref=backref('tasks_positioned', cascade='all, delete-orphan')) 
    task = relationship(Task, foreign_keys='PositionedTask.task_id') 

    def __init__(self, task=None, parent=None, position=None): 
     self.task = task 
     self.parent = parent 
     self.position = position 

    def __repr__(self): 
     return '<PositionedTask parent=\'{0}\' task=\'{1}\' position={2}>'.format(
      self.parent.title, self.task.title, self.position 
     ) 


def main(argv=sys.argv): 
    engine = create_engine('sqlite:///test.db', echo=False) 
    Base.metadata.create_all(engine) 
    session = Session(engine) 

    task = Task('Parent') 
    child1 = Task('Child #1', done=True) 
    child2 = Task('Child #2') 
    grandchild1 = Task('GrandChild #1') 

    child1.tasks.append(grandchild1) 
    task.tasks.append(child1) 
    task.tasks.append(child2) 

    session.add(task) 
    session.commit() 

    task = session.query(Task).filter(Task.id==1).first() 
    print task 
    for st in task.tasks: 
     print st 
    for pst in task.tasks_positioned: 
     print pst 

if __name__ == '__main__': 
    main() 

當前應用程序的輸出是:

<Task #1 'Parent' done=False> 
<Task #2 'Child #1' done=True> 
<Task #4 'Child #2' done=False> 
<PositionedTask parent='Parent' task='Child #1' position=0> 
<PositionedTask parent='Parent' task='Child #2' position=0> 

我怎樣才能在sqlalchemy.ext.orderinglist.ordering_list混合到這段代碼讓我的子任務自動定位?

回答

0

只需修改PositionedTask.parent關係backref部分,瞧:

parent = relationship(
    Task, 
    foreign_keys='PositionedTask.parent_id', 
    backref=backref(
     'tasks_positioned', 
     order_by ="PositionedTask.position", # @new: 
     collection_class=ordering_list('position'), # @new: 
     cascade='all, delete-orphan'), 
    ) 
相關問題