我刚刚添加了应该可以解决您的问题的预取功能。您可以从GitHub 存储库中获取工作代码。此功能将成为即将发布的 Pony ORM 0.5.4 的一部分。
现在你可以写:
q = q.prefetch(Supplier)
或者
q = q.prefetch(Order.supplier)
并且 Pony 会自动加载相关supplier
的对象。
下面我将使用带有 Student、Groups 和 Departments 的标准 Pony 示例展示几个带有预取的查询。
from pony.orm.examples.presentation import *
仅加载 Student 对象,不进行任何预取:
students = select(s for s in Student)[:]
将学生与组和部门一起加载:
students = select(s for s in Student).prefetch(Group, Department)[:]
for s in students: # no additional query to the DB is required
print s.name, s.group.major, s.group.dept.name
与上面相同,但指定属性而不是实体:
students = select(s for s in Student).prefetch(Student.group, Group.dept)[:]
for s in students: # no additional query to the DB is required
print s.name, s.group.major, s.group.dept.name
加载学生及其课程(多对多关系):
students = select(s for s in Student).prefetch(Student.courses)
for s in students:
print s.name
for c in s.courses: # no additional query to the DB is required
print c.name
作为prefetch()
方法的参数,您可以指定实体和/或属性。如果您指定了一个实体,那么所有具有此类型的一对一属性都将被预取。如果您指定了一个属性,那么这个特定的属性将被预取。多对多属性仅在显式指定时才被预取(如Student.courses
示例中所示)。预取是递归进行的,因此您可以加载长链属性,例如student.group.dept
.
当对象被预取时,默认情况下它的所有属性都被加载,除了惰性属性和多对多属性。如果需要,您可以显式预取惰性和多对多属性。
我希望这种新方法完全涵盖您的用例。如果某些事情没有按预期工作,请在 GitHub 上开始新问题。您还可以在Pony ORM 邮件列表中讨论功能并提出功能请求。
PS 我不确定您使用的存储库模式是否会给您带来严重的好处。我认为它实际上增加了模板渲染和 repo 实现之间的耦合,因为当模板代码开始使用新属性时,您可能需要更改 repo 实现(即添加新实体到预取列表)。使用顶级@db_session
装饰器,您只需将查询结果发送到模板,一切都会自动发生,无需显式预取。但也许我遗漏了一些东西,所以我有兴趣看到关于在您的案例中使用存储库模式的好处的更多评论。