Django - сортировка QuerySet потоковых комментариев - PullRequest
0 голосов
/ 25 августа 2011

Я использую django-threadadedcomments , однако вопрос обычно относится и к сортировке 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' и т. Д. *

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

Но я не могу понять, как сортировать комментарии без полномочий root одновременно.Я пробовал что-то вроде:

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 ]

3 голосов
/ 14 января 2012

Я понимаю, что прошло немного времени с тех пор, как вы отправили сообщение ... поэтому вы можете получить ответ к этому моменту или, возможно, вы ушли. Независимо от того, вы идете ...:)

Вы неправильно понимаете структуру tree_path в приложении django-threadadedcomments. Tree_path никогда не будет равным 1/1, поскольку каждый сегмент пути является уникальным первичным ключом этого 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

Если у кого-то есть способ сократить это, не стесняйтесь внести свой вклад.

0 голосов
/ 14 января 2012

Как насчет того, чтобы сначала выбрать только корневые комментарии, упорядочить их, а затем выбрать дочерние комментарии, упорядочить их и, наконец, объединить оба набора?Будет ли это работать?

...