嵌套对象的查询集排序

Queryset ordering for nested objects

我需要在我的项目中使用 REST 构建一个简单的嵌套评论系统 API。

有一些要求:

该页面应包含所有评论的分页,而不仅仅是父评论。所以,如果有 1 条评论和 20 条来自其他用户的嵌套评论,那么在第一页应该显示,如下所示:

-Comment 1

-- Sub comment 1

-- ...

-- Sub comment 9

On the second page:

-- Sub comment 10

-- ...

-- Sub comment 19

On the third page:

-- Sub comment 20

并且应该是数据库访问最少的最优解。

我想知道自定义 Queryset 排序,当每个评论后面跟着嵌套评论时,就像这样:

// Note, that ids follow in chaotic order
{
    id: 1,
    text: "Comment 1",
    parent: null
}, 
{
    id: 5,
    text: "Sub comment 1 for Comment 1",
    parent: 1
}, 
{
    id: 6,
    text: "Sub comment 2 for Comment 1",
    parent: 1
}, 
{
    id: 2,
    text: "Comment 2",
    parent: null
}, 
{
    id: 3,
    text: "Sub comment 1 for Comment 2",
    parent: 2
}, 
{
    id: 4,
    text: "Sub comment 2 for Comment 2",
    parent: 2
}, 

我也想 google 关于 Django-mptt,但不知道如何实现它。你能给我建议,如何解决这个问题并像我的例子一样得到 JSON 吗?

您可以使用 <parent>_<id> 的复合排序键对 children 和 <id> 的根注释进行注释,并按其排序。在示例中,评论将具有排序键 1, 1_5, 1_6, 2, 2_3, 2_4.

from django.db.models import CharField, Value as V
from django.db.models.functions import Concat

Comment.objects
    .annotate(sort_key=Case(
        When(parent__isnull=True, then=Concat('id', V('_0'), output_field=CharField())),
        When(parent__isnull=False, then=Concat('parent', V('_'), 'id', output_field=CharField())),
        output_field=CharField())
    .order_by('sort_key')

如果 children 可以按 id 排序并且不需要按日期或类似排序,这当然只是一个有效的解决方案。如果您需要 children 的另一个排序顺序,您可能需要在聚合中对它们的顺序进行排序后用索引显式注释它们。

参见:

编辑: 将 parents 的排序键更改为 1_0。解决了 int 与 char 比较的问题。当然,演员表也可以。