0

私はdjango-threadedcommentsを使用していますが、質問は一般的に QuerySet のソートにも当てはまります。

QuerySet のコメント オブジェクトには、tree_path と submit_date という 2 つの重要なフィールドがあります。tree_path の形式は「a/b/.../z」です。「a」はツリーの最上位のインデックスで、「b」はツリーの最下位のインデックスです。したがって、最初のルート コメントの tree_path は「1」になります。そのコメントの子には、「1/1」の tree_path があります。「1」の別の子には、「1/2」の tree_path があります。2 番目のルート コメントの root_path は「2」などになります。

QuerySet "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')

しかし、それはコメントのスレッド化を破壊します。

助言がありますか?ありがとう!

4

2 に答える 2

4

あなたが投稿してから少し時間が経っていることに気づきました..だから、今までに答えがあるかもしれません。とにかく、どうぞ... :)

django-threadedcomments アプリケーションの tree_path 構造を誤解しています。各パス セグメントはその ThreadedComment の一意の主キーであるため、1/1 の tree_path はありません。

ThreadedComment1から始めて返信を追加すると、 のパスが得られます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

誰かがこれを短縮する方法を持っている場合は、遠慮なく貢献してください。

于 2012-01-13T20:27:25.970 に答える
0

最初にルート コメントだけを選択して並べ替え、次に子コメントを選択して並べ替え、最後に両方のセットを連結するのはどうでしょうか。それはうまくいきますか?

于 2012-01-14T17:58:07.160 に答える