views:

20

answers:

1

Let's say I have a Task object which can be dependent on other Tasks. Is there a way to sensibly eager/joinedload all of a given set of task's subtasks?

class Task(DeclarativeBase):
    __tablename__ = 'task'

    task_id = Column(Integer, primary_key=True)
    name = Column(String, unique=True)

    def add_dependencies(self, *tasks):
        for task in tasks:
            TaskDependency(dependent=self, dependency=task)
        return self

    @property
    def dependencies(self):
        return [x.dependency for x in self.dependency_edges]

    @dependencies.setter
    def dependencies(self, what):
        "Note: adds dependencies, doesn't remove them" 
        self.add_dependencies(*what)

    @property        
    def dependents(self):
        return [x.dependent for x in self.dependent_edges]

class TaskDependency(DeclarativeBase):
    __tablename__ = 'task_dependency'

    dependent_id = Column(Integer, ForeignKey(Task.task_id), primary_key=True)                        
    dependency_id = Column(Integer, ForeignKey(Task.task_id), primary_key=True)

    dependent = relationship(Task, primaryjoin=dependent_id == Task.task_id, 
                             backref='dependent_edges')

    dependency = relationship(Task, primaryjoin=dependency_id == Task.task_id, 
                              backref='dependency_edges')

def example_task_maker():
    make_cheese = Task(
        name="MAKE_CHEESE",
        dependencies=[
            Task(name="MILK_COWS",
                dependencies=[
                    Task(name="BUY_COWS")
                ]),
        ]
    )


def load_task()
    # How to eagerly load the whole task tree here?
    DBSession.query(Task).filter(name="MAKE_CHEESE").all()
A: 

Ah. What I was actually after was an adjacency list, of which there are examples to be found here, which I missed:

http://www.sqlalchemy.org/docs/05/mappers.html#adjacency-list-relationships

I believe this will do what I was after.

pwaller