SQLAlchemy和Traversal:如何为从数据库中检索的对象添加遍历必需属性?

时间:2013-02-28 06:23:31

标签: python sqlalchemy pyramid traversal

我有这样的资源树结构:

Root
|
|
\-- Article
|     |
|     \-- 1
|     \-- 2
|
\-- User
      |
      \-- 1
      \-- 2

当用户访问“/ Article”时,我将显示所有文章的列表:

@view_config(context='resource.ArticleDispatcher', renderer='nothing-related')
def article_list(context, resource):
    articles = request.db.query(Article)
    return {'articles': articles}

但是在模板中,我发现我无法调用'req.resource_url(ARTICLE_OBJECT)'因为我从数据库中检索到的对象'文章'既没有名称也没有父< / strong>设置。

现在我不知道如何在这种情况下生成URL ... :-(我的设计是不正确的?

1 个答案:

答案 0 :(得分:2)

为了让你的文章对象自动正确地插入到遍历树中,最直接的方法是通过父__getitem__方法访问它们,如果您访问单个文章,这种方法就可以正常工作:{ {1}}

当你显示一个列表时,你并没有真正遍历各篇文章,你想在/Articles/123显示文章列表只是巧合,所以这种情况不会被遍历直接覆盖(这是关于遍历URI )。有一些快速修复,使它看起来像是遍历:

/Articles

在这里,你以某种方式知道你需要的所有文章的所有ID,并通过遍历逐个获取子项,将它们插入到遍历上下文中。在许多情况下(特别是使用SQL后端),这将不是非常有效,因为您需要为每个对象发出单独的查询。

其次,更现实的例子:手动将文章插入遍历上下文:

@view_config(context='resource.ArticleDispatcher')
def article_list(context, request):
    all_articles_ids = context.magically_get_ids_of_all_articles()
    articles = [context[id] for id in all_articles_ids]
    return {'articles': articles}

第三个例子:不要假装你正在浏览文章而只是做一些像

这样的事情
@view_config(context='resource.ArticleDispatcher')
def article_list(context, request):
    articles = context.adopt_children(request.db.query(Article))
    return {'articles': articles}

class ArticleDispatcher(object):
    def adopt_children(self, children):
        for child in children:
            child.__name__ = child.id # actually I'd made __name__ a property of the Article model
            child.__parent__ = self
        return children

在这种情况下,您甚至可能不需要查询完整的文章对象,您可能只查询名称和ID(在某些情况下可能更快):

req.resource_url(ARTICLE_DISPATCHER) + '/' + article.id