如何获取 Flask-SQLAlchemy 对象来加载 Jinja 模板的关系子项?
-
21-12-2019 - |
题
我有用户和帖子的基本模型。在我的用户模型中,我有
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 %}
不幸的是,这不起作用。Posts 是一个查询,而不是一个对象 b/c lazy='dynamic'
. 。如果我改变的话我可以做到以上 lazy='joined'
, ,但是每当我查询用户时,它都会加载用户的所有帖子。
我尝试添加 .options(joinedload('posts'))
对于我的询问,但它说
无效请求错误:“User.posts”不支持对象填充 - 无法应用急切加载。
任何帮助表示赞赏。
解决方案
只需删除 lazy="dynamic"
参数,你将能够使用 joinedload
没有问题。(请记住,当您这样做时,您将面临难以诊断的 N+1 查询问题。如果您始终需要这些帖子,请使用 joined
反而)。
如果您需要所有行为(可查询、可连接和延迟加载),我建议查看答案 这个问题, ,这建议为动态查询添加另一个属性:
class User(db.Model):
posts = db.relationship('Post', backref='user')
class Post(db.Model):
# etc.
User.posts_query = db.relationship(Post, lazy='dynamic')
其他提示
它是一个 查询对象 是的,但是这些查询对象具有可能对您有帮助的方法。针对此用例,您可以执行以下操作:
{% for user in users %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.posts.count() }}</td>
</tr>
{% endfor %}
您必须对查询对象执行 .first() 或 .all() 才能获取实际的对象/列表。例如
users = User.query.all()
不隶属于 StackOverflow