【问题标题】:Efficient Pagination from Join in Django在 Django 中加入高效分页
【发布时间】:2010-12-24 02:00:43
【问题描述】:

我在连接和分页方面遇到了问题。我有 3 个模型:

  • 标签
  • 标签关系

我使用标签关系来管理 Pad 和标签之间的多对多关系(使用 ManyToMany 字段的 through 属性)。 现在,当我在 Pad 和 Tag 表上进行连接时,它给了我类似的东西......

pad.name   tag.name     etc
---------------------------
pad1       tag1         ...
pad1       tag2         ...
pad2       tag3         ...

现在,当我根据这些结果创建 Paginator() 对象时,显然每页的项目计数错误。我将不得不遍历所有结果并生成这样的字典...

[{name:'pad1', tags:['tag1', 'tag2']}, {name:'pad2' ....]

...并在此使用 Paginator 来获取正确的页面。

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

结果的内容也可能很长,并且遍历整个集合会消耗大量系统内存(或者会不会?启发我:))。

【问题讨论】:

    标签: sql django join pagination


    【解决方案1】:

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

    thispagepadids = [o.id for o in mypageobject.object_list]
    tagrels = TagRelation.objects.filter(pad__id__in=thispagetagids).select_related('tag','pad'))
    

    (假设您的页面对象在 mypageobject 中)。 然后,您可以在代码中获取任何给定 tagrel 的 pad 和标签(使用 regroup 模板标签可能是最简单的方法)但数据库只执行一个(巨型)查询,并且您的分页计数仍然正确。

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

    【讨论】:

    • 不幸的是,这也不允许我按标签过滤条目。似乎没有办法绕过巨大的连接和手动(代码内)后处理。
    • 啊,但是如果您想按标签过滤(假设您只谈论一个特定标签),您可以安全地再次对 TagRelation 进行分页,并且只有:TagRelation.objects.filter(tag=someTagObject ) 因为您的分页对象应该为每个 Pad 提供一个 Tagrel(假设您不能多次使用相同的 Tag 标记一个 Pad)。
    猜你喜欢
    • 2013-04-16
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多