2014-02-25 38 views
7

我有用户和帖子的基本模型。在我的用户模型中,我有如何让Flask-SQLAlchemy对象为Jinja模板加载关系子对象?

posts = db.relationship('Post', backref='user', lazy='dynamic') 

然而,当我这样做

return render_template('user.html', users=users) 

我想要做的东西一样

{% for user in users %} 
    <tr> 
     <td>{{ user.id }}</td> 
     <td>{{ user.posts|length }}</td> 
    </tr> 
{% endfor %} 

不幸的是,这是行不通的。帖子是查询,而不是lazy='dynamic'的对象b/c。如果我更改了lazy='joined',我可以执行上述操作,但是随时会为用户查询用户时加载所有帖子。

我尝试添加.options(joinedload('posts'))我的查询,但它说,

InvalidRequestError: 'User.posts' does not support object population - eager loading cannot be applied.

任何帮助表示赞赏。

回答

7

只要简单地除去lazy="dynamic"参数,你将能够使用一个joinedload没有问题。 (请记住,当你这样做时,你会打开自己的诊断N + 1的疑难问题。如果你总是需要这些帖子,请改为使用joined)。

如果你需要的所有行为(可查询,可连接,和懒加载),我建议在寻找答案this question,这表明增加了对动态查询另一个属性:

class User(db.Model): 
    posts = db.relationship('Post', backref='user') 

class Post(db.Model): 
    # etc. 

User.posts_query = db.relationship(Post, lazy='dynamic') 
0

这是一个query object是的,但这些查询对象的方法可能会帮助你。特别是用于该用途的情况下,你可以这样做:

{% for user in users %} 
    <tr> 
     <td>{{ user.id }}</td> 
     <td>{{ user.posts.count() }}</td> 
    </tr> 
{% endfor %} 
+4

这将导致'N + 1'查询(其中'1'得到用户和'N'是返回的用户数量),因为'count'会去取总数为每个用户从数据库中为该用户发布的帖子。 –

+0

@SeanVieira如果我只需要计算项目,我最好使用默认懒惰(即'select'),然后使用Jinja的'length'来获取模板中的计数,而不是使用'lzay ='dynamic' COUNT()'? –

+2

如果你需要的只是'User,post count',你实际上可以更好地使用单独的查询 - 如果你打算在渲染模板时使用所有的帖子,那么yes |长度“是你想要的,而不是为每个用户发布一个”计数“。 –

-1

必须执行。首先()或.all()到您的查询对象来获取实际的对象/列表。 如
users = User.query.all()