我试图创建一个简单的任务树结构。任务可以具有状态(完成:布尔)和标题(标题:字符串)和任意数量的子任务(任务:任务[])。我成功地设法创建了一个Task对象和关联代理对象PositionedTask。父/子关系似乎有效,尽管定位未被使用。
这是我到目前为止所获得的代码:
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 :(得分:0)
只需修改backref
关系的PositionedTask.parent
部分,即可:
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'),
)