python - 嵌套对象的查询集排序
问题描述
我需要在我的项目中使用 REST API 构建一个简单的嵌套评论系统。
有一些要求:
该页面应包含所有评论的分页,而不仅仅是父评论。因此,如果有 1 条评论和 20 条来自其他用户的嵌套评论,则应在第一页显示,如下所示:
-评论 1
-- 子评论 1
-- ...
-- 子评论 9
在第二页:
-- 子评论 10
-- ...
-- 子评论 19
在第三页:
-- 子评论 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
},
我也想过和谷歌关于 Django-mptt,但不知道如何实现它。您能向我建议如何解决这个问题并像我的示例中那样获取 JSON 吗?
解决方案
您也许可以使用来自<parent>_<id>
子级和<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')
这当然只是一个有效的解决方案,如果孩子可以id
按日期或类似排序而不需要按日期排序。如果您需要对子项进行另一种排序顺序,则可能需要在对它们在聚合中的顺序进行排序后使用索引显式注释它们。
看:
- https://docs.djangoproject.com/en/3.0/topics/db/aggregation/
- https://docs.djangoproject.com/en/3.0/ref/models/conditional-expressions/#case
- https://docs.djangoproject.com/en/3.0/ref/models/database-functions/#concat
编辑:将父母的排序键更改为 1_0。解决了 int 与 char 比较的问题。当然,演员阵容也可以。
推荐阅读
- xml - XML 用数字增加特定值
- r - 在 PyCharm 中使用 R 插件绘制图形
- asp.net - asp.net MVC切换用户
- javascript - 当子 div 不存在时隐藏 div
- node.js - 从 MongoDB 或文件(内存)中获取数据
- node.js - 垃圾收集时 NodeJS ref-struct 中的损坏内容
- javascript - 如何使用 imacros 浏览器提取 javascript 变量值?
- javascript - 我需要帮助从我的 MVC 控制器调用方法并使用 ajax 返回其返回值(int)
- reactjs - mount() 失败,因为目标容器不是 dom 元素
- python-2.7 - 为什么即使在关闭会话后,Python-Requests 在循环中发出 POST 时也会返回相同的数据?