Сортировать и ограничить набор запросов по количеству комментариев и дате, используя queryset.extra () (django) - PullRequest
1 голос
/ 30 мая 2010

Я пытаюсь отсортировать / сузить набор запросов объектов по количеству комментариев каждого объекта, а также по срокам, в течение которых комментарии были опубликованы. Я использую метод queryset.extra() (используя django_comments, который использует общие внешние ключи).

У меня появилась идея использовать queryset.extra() (и код) отсюда . Это дополнительный вопрос к моему первоначальному вопросу вчера (который показывает, что я делаю некоторый прогресс).

Текущий код:

То, что у меня есть, работает так, что оно будет отсортировано по количеству комментариев; однако я хочу расширить функциональность, а также иметь возможность передавать аргумент временного интервала (например, 7 дней) и возвращать упорядоченный список наиболее комментируемых постов за этот период времени.

Вот как выглядит мой взгляд с базовым функционалом в такте:

import datetime
from django.contrib.comments.models import Comment
from django.contrib.contenttypes.models import ContentType
from django.db.models import Count, Sum
from django.views.generic.list_detail import object_list

def custom_object_list(request, queryset, *args, **kwargs):
    '''Extending the list_detail.object_list to allow some sorting.

    Example: http://example.com/video?sort_by=comments&days=7

    Would get a list of the videos sorted by most comments in the 
    last seven days.
    '''

    try: # this is where I started working on the date business ... 
        days = int(request.GET.get('days', None))
        period = datetime.datetime.utcnow() - datetime.timedelta(days=int(days))
    except (ValueError, TypeError):
        days = None
        period = None

    sort_by = request.GET.get('sort_by', None)
    ctype = ContentType.objects.get_for_model(queryset.model)

    if sort_by == 'comments':
        queryset = queryset.extra(select={
            'count' : """
                SELECT COUNT(*) AS comment_count
                FROM django_comments
                WHERE
                    content_type_id=%s AND
                    object_pk=%s.%s
            """ % ( ctype.pk, queryset.model._meta.db_table, 
                queryset.model._meta.pk.name ),
            },
            order_by=['-count']).order_by('-count', '-created')

    return object_list(request, queryset, *args, **kwargs)

Что я пробовал:

Я не очень хорошо разбираюсь в SQL, но я пытался просто добавить еще один WHERE критерий вручную, чтобы посмотреть, смогу ли я добиться определенного прогресса:

    SELECT COUNT(*) AS comment_count
    FROM django_comments
    WHERE
        content_type_id=%s AND
        object_pk=%s.%s AND
        submit_date='2010-05-01 12:00:00'    

Но это ничего не сделало, кроме как возиться с моим порядком сортировки.

Есть идеи, как мне добавить этот дополнительный уровень функциональности?

Спасибо за любую помощь или понимание.

1 Ответ

1 голос
/ 30 мая 2010

Попробуйте [обновлено, чтобы включить разницу во времени (cutoff_date)]

 queryset = queryset.extra(select={
            'comment_count' : """
                SELECT COUNT(*)
                FROM django_comments
                WHERE
                    django_comments.content_type_id=%s AND
                    django_comments.object_pk=%s.%s AND
                    django_comments.submit_date < '%s'
            """ % ( ctype.pk, 
                    queryset.model._meta.db_table, 
                    queryset.model._meta.pk.name,
                    cutoff_date ),
            }).order_by('-comment_count', '-created')

Чтобы получить хорошее значение cutoff_date, я бы порекомендовал использовать внушительную информацию в модуле python-dateutil :

from datetime import relativedelta
from datetime import date

cutoff_date = date.today() - relativedelta(weeks =1) #relativedelta does all the heavy lifting
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...