Sql Django中来自Join的高效分页

Sql Django中来自Join的高效分页,sql,django,join,pagination,Sql,Django,Join,Pagination,我这里有一个连接和分页的问题。我有3种型号: 垫 标签 标记关系 我使用Tag relation来管理焊盘和标记之间的多个关系(使用te manytomy字段的through属性)。 现在,当我在Pad和Tag表上进行连接时,它会给我这样的结果 pad.name tag.name etc --------------------------- pad1 tag1 ... pad1 tag2 ... pad2 ta

我这里有一个连接和分页的问题。我有3种型号:

  • 标签
  • 标记关系
我使用Tag relation来管理焊盘和标记之间的多个关系(使用te manytomy字段的through属性)。 现在,当我在Pad和Tag表上进行连接时,它会给我这样的结果

pad.name   tag.name     etc
---------------------------
pad1       tag1         ...
pad1       tag2         ...
pad2       tag3         ...
[{name:'pad1', tags:['tag1', 'tag2']}, {name:'pad2' ....]
现在,当我根据这些结果创建Paginator()对象时,很明显,每页的项目计数是错误的。我将不得不迭代所有的结果,并生成这样一个字典

pad.name   tag.name     etc
---------------------------
pad1       tag1         ...
pad1       tag2         ...
pad2       tag3         ...
[{name:'pad1', tags:['tag1', 'tag2']}, {name:'pad2' ....]
。。。并使用此页面上的分页器获取正确的页面

解决这个问题的最佳方法是什么?我可以对当前页面上的每个Pad对象进行DB查询,以获取其标记,但我猜这迟早会杀死服务器(应该是性能)


结果的内容也可能相当长,在整个集合中进行迭代将消耗大量的系统内存(或者它会不会?启发我:)。

如果我理解正确,您应该在Pad.objects.all()上分页,然后在TagRelation对象上使用a,以两种方式在一个(附加)中获取适当的标记查询,并在视图/模板中使用该数据。比如:

thispagepadids = [o.id for o in mypageobject.object_list]
tagrels = TagRelation.objects.filter(pad__id__in=thispagetagids).select_related('tag','pad'))
(假设您的页面对象位于mypageobject中)。 然后,您可以在代码中获取任何给定tagrel的pad和tag(使用模板标记可能是最简单的方法),但是DB只执行一个(巨人)查询,并且您的分页计数仍然正确


请注意,我们必须执行这两个查询,因为您不能在多对多字段上直接使用select_related(请参阅),但您可以使用它从中间m2m表双向跟踪FKs。

不幸的是,这不允许我也按标记筛选条目。似乎没有办法绕过巨大的连接和手动(在代码中)后处理。啊,但是如果你想按标签过滤(假设你只说一个特定的标签),你可以安全地重新分页TagRelation,而且只有:TagRelation.objects.filter(tag=someTagObject)作为分页对象,每个Pad应该给你一个Tagrel(假设不能多次使用同一标记标记一个焊盘)。