SQLAlchemy和遍历:如何为从数据库检索的对象添加遍历所需属性?
我有一个资源树结构,像这样:
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)',因为我从数据库中获取的 'articles' 对象既没有名称也没有父级设置。
现在我不知道在这种情况下该如何生成网址... :-( 我的设计是不是有问题?
1 个回答
3
为了让你的文章对象能够自动正确地插入到遍历树中,最直接的方法是通过父对象的 __getitem__
方法来访问它们。如果你只是访问单个文章,比如 /Articles/123
,这样做是没问题的。
但是,当你要显示一个文章列表时,其实并不是在逐个访问文章。你只是碰巧想在 /Articles
显示一系列文章,所以这个情况并不直接适用于遍历(遍历是指 访问一个URI)。不过,有几种简单的方法可以让它看起来像是在进行遍历:
@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}
在这里,你需要知道所有文章的ID,然后通过遍历一个一个地获取它们的子项,这样就能把它们插入到遍历上下文中。不过在很多情况下(尤其是使用SQL数据库时),这样做效率并不高,因为你需要为每个对象单独发起一个查询。
第二个,更现实的例子是:手动将文章插入到遍历上下文中:
@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
第三个例子是:干脆不去假装你在遍历文章,而是直接做一些像这样的事情:
req.resource_url(ARTICLE_DISPATCHER) + '/' + article.id
在这种情况下,你甚至可能不需要查询完整的文章对象,只需要查询名称和ID(在某些情况下这样可能会更快):
@view_config(context='resource.ArticleDispatcher')
def article_list(context, resource):
name_id_tuples = request.db.query(Article.id, Article.name).all()
return {'articles': name_id_tuples}