Django - 对线程注释的QuerySet进行排序

时间:2011-08-24 23:31:13

标签: django sorting comments django-queryset threaded-comments

我正在使用django-threadedcomments,但问题通常也适用于对QuerySet进行排序。

QuerySet中的注释对象有两个重要的字段,tree_path和submit_date。 tree_path的形式为“a / b /.../ z”,其中“a”是树中的最高阶索引,“b”是树中的最低阶索引。所以第一个根注释的tree_path为'1'。该注释的子项将具有“1/1”的tree_path。另一个'1'的孩子将有一个'1/2'的tree_path。第二个根注释的root_path为“2”,等等......

QuerySet“qs”按上面的顺序排序,其中的评论采用线程顺序排列,最旧的评论位于顶部。只是上面例子的tree_paths看起来像[1,1 / 1,1 / 2,1]。我想先用最新的评论对每个级别的评论进行排序。所以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')

但这会摧毁评论的线索。

有什么建议吗?谢谢!

2 个答案:

答案 0 :(得分:3)

我意识到这已经有一段时间了,因为你发布了..所以你现在可能有一个答案,或者你可能已经继续前进了。无论如何,你去...... :)

您误解了django-threadedcomments应用程序中的tree_path结构。永远不会有一个1/1的tree_path,因为每个路径段都是ThreadedComment的唯一主键。

如果您从ThreadedComment 1开始,并添加回复,您将获得1/2的路径。然后,如果您添加其他顶级帖子,则会获得路径3。这会给你:

1
1/2
3

如果你再次回复第一篇文章,你会得到:

1
1/2
1/4
3

现在解决排序问题。我试图进行类似的排序(通过投票得分,类似于reddit),并没有找到简单的方法。但是,这里有一个你可以使用的递归方法:(它很丑,而且很慢......但它是一个起点)

def sort_comments(tree):
    final_tree = []
    root_comments = [c for c in tree if c.tree_path.count('/') == 0]
    root_comments.sort(key=lambda comment: comment.submit_date, reverse=True)
    for comment in root_comments:
        final_tree.append(comment)
        append_and_sort_children(final_tree, tree, comment)
    return final_tree


def append_and_sort_children(final_tree, tree, parent):
    children = [c for c in tree if c.parent_id == parent.id]
    children.sort(key=lambda comment: comment.submit_date, reverse=True)
    for comment in children:
        final_tree.append(comment)
        append_and_sort_children(final_tree, tree, comment)

使用它,只需传入该模型的整个查询评论集,python就会为您排序。 :)

这将为您提供以下最终结果:

3
1
1/4
1/2

如果有人有办法缩短这一点,请随时捐款。

答案 1 :(得分:0)

如何首先选择根注释,排序它们然后选择子注释并对它们进行排序并最终连接两组?那会有用吗?