Django - 对线程评论的查询集进行排序
我正在使用 django-threadedcomments,但是这个问题通常也适用于对 QuerySet 进行排序。
QuerySet中的评论对象有两个重要的字段,tree_path和submit_date。 tree_path 的形式为“a/b/.../z”,其中“a”是树中的最高阶索引,“b”是树中的最低阶索引。因此第一个根注释的 tree_path 将为“1”。该注释的子级的 tree_path 为“1/1”。 “1”的另一个子级的 tree_path 将为“1/2”。第二个根注释的 root_path 为“2”,等等...
查询集“qs”按上面的方式排序,注释按线程顺序排列,最旧的注释位于顶部。上面示例的 tree_paths 看起来像 [1, 1/1, 1/2, 2]。我想先将每个级别的评论与最新的评论进行排序。因此 QuerySet 应该是 [2, 1, 1/2, 1/1]。
我该怎么做?
我可以使用以下方法仅对根级评论进行排序:
qs = qs.extra(select={ 'tree_path_root': 'SUBSTRING(tree_path, 1, 1)' })
.order_by('%stree_path_root' % ('-'), 'tree_path')
但我无法弄清楚如何同时对非根级评论进行排序。我尝试过类似的方法:
qs = qs.extra(select={ 'tree_path_root': 'SUBSTRING(tree_path, 1, 1)'
'tree_path_sec' : 'SUBSTRING(tree_path, 3, 1)'})
.order_by('%stree_path_root' % ('-'), '%stree_path_sec' % ('-'), 'tree_path')
但这会破坏评论的线索。
有什么建议吗?谢谢!
I am using django-threadedcomments, however the question also applies generally to sorting a QuerySet.
The comment objects in the QuerySet have two important fields, tree_path and submit_date. tree_path is of the form "a/b/.../z" where 'a' is the highest-order index in the tree, and 'b' is the lowest order index in the tree. So the first root comment will have a tree_path of '1'. A child of that comment will have a tree_path of '1/1'. Another child of '1' will have a tree_path of '1/2'. The second root comment will have a root_path of '2', etc...
The QuerySet "qs" is sorted like above, with comments in threaded order with the oldest comments on top. Just the tree_paths of the above example would look like [1, 1/1, 1/2, 2]. I would like to sort each level of comments with the newest comments first. So the QuerySet instead should be [2, 1, 1/2, 1/1].
How can I do this?
I can sort just the root level comments by using:
qs = qs.extra(select={ 'tree_path_root': 'SUBSTRING(tree_path, 1, 1)' })
.order_by('%stree_path_root' % ('-'), 'tree_path')
But I cannot figure out how to sort the non-root comments at the same time. I've tried something like:
qs = qs.extra(select={ 'tree_path_root': 'SUBSTRING(tree_path, 1, 1)'
'tree_path_sec' : 'SUBSTRING(tree_path, 3, 1)'})
.order_by('%stree_path_root' % ('-'), '%stree_path_sec' % ('-'), 'tree_path')
But that destroys the threading of the comments.
Any suggestions? Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我意识到自从您发布以来已经有一段时间了..所以您现在可能已经有了答案,或者也许您已经继续前进。无论如何,在这里...:)
您误解了 django-threadedcomments 应用程序中的 tree_path 结构。永远不会有 1/1 的 tree_path,因为每个路径段都是该 ThreadedComment 的唯一主键。
如果您从 ThreadedComment
1
开始,并添加回复,您将获得1/2
路径。然后,如果您添加额外的顶级帖子,它将获得路径3
。这将为您提供:如果您再次回复第一篇帖子,您将得到:
现在解决排序问题。我尝试过进行类似的排序(通过投票分数,类似于 reddit),但发现没有简单的方法来做到这一点。然而,这里有一个你可以使用的递归方法:(它很丑陋,而且很慢......但它是一个起点)
使用这个方法,只需传入该模型的整个查询注释集,Python 就会对它们进行排序你。 :)
这会给你最终的结果:
如果有人有办法缩短这个时间,请随意贡献。
I realize this has been a little while since you posted.. so you may have an answer by now, or maybe you have moved on. Regardless, here you go... :)
You are misunderstanding the tree_path structure in the django-threadedcomments application. There will never be a tree_path of 1/1, as each path segment is the unique primary key of that ThreadedComment.
If you start with ThreadedComment
1
, and add a reply, you will get a path of1/2
. Then if you add an additional top-level post, it would get the path3
. This would give you:And if you reply to the first post again, you would get:
Now to address the sorting issue. I have attempted to do a similar sorting (by a voting score, similar to reddit), and found no easy way to do it. However, here is a recursive method that you can use: (It is ugly, and slow... but its a starting point)
Using this, simply pass in your entire query set of comments for that model, and python will sort them for you. :)
This will give you the final result of:
If anyone has a way to shorten this, feel free to contribute.
首先只选择根评论,对它们进行排序,然后选择子评论并对它们进行排序,最后连接两组评论怎么样?那行得通吗?
How about selecting just the root comments first, ordering them and then selecting the child comments and ordering them and finally concatenating both sets? Will that work?