如何让Flask-SQLAlchemy对象为Jinja模板加载关系子元素?

时间:2014-02-25 15:59:43

标签: python sqlalchemy flask jinja2 flask-sqlalchemy

我有User和Post的基本模型。在我的用户模型中,我有

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'不支持对象填充 - 无法应用急切加载。

感谢任何帮助。

3 个答案:

答案 0 :(得分: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')

答案 1 :(得分:0)

这是query object是的,但这些查询对象有可能对您有帮助的方法。特别针对此用例,您可以执行以下操作:

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

答案 2 :(得分:-1)

您必须对查询对象执行.first()或.all()以获取实际的对象/列表。 e.g
BufferedReader br = null; try{ connection = new URL(xml).openConnection(); Scanner scanner = new Scanner(connection.getInputStream()); while (scanner.hasNextLine()) { String line = scanner.nextLine(); content = content +line; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } Document document = Jsoup.parse(content);