【问题标题】:Sort and limit queryset by comment count and date using queryset.extra() (django)使用 queryset.extra() (django) 按评论计数和日期对查询集进行排序和限制
【发布时间】:2011-02-25 16:20:55
【问题描述】:

我正在尝试根据每个对象具有的 cmets 数量以及发布 cmets 的时间范围对对象的查询集进行排序/缩小。我正在使用queryset.extra() 方法(使用django_comments,它使用通用外键)。

我想到了使用queryset.extra()(和代码)from here。这是my initial question yesterday 的后续问题(这表明我正在取得一些进展)。

当前代码:

到目前为止,我所做的工作是按照 cmets 的数量进行排序;但是,我想扩展功能,并且能够传递时间框架参数(例如,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'    

但这并没有做任何事情,除了弄乱我的排序顺序。

关于如何添加这一额外功能层的任何想法?

感谢任何帮助或见解。

【问题讨论】:

    标签: python sql mysql django


    【解决方案1】:

    试试这个[更新到包括时差(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')
    

    为了获得一个好的截止日期,我建议使用来自python-dateutil 模块的 awesome-in-a-box relativedelta:

    from datetime import relativedelta
    from datetime import date
    
    cutoff_date = date.today() - relativedelta(weeks =1) #relativedelta does all the heavy lifting
    

    【讨论】:

    • 这确实有效,但是,我仍然希望能够计算在特定时间范围内(例如过去 7 天)发布在对象上的 cmets 数量。现在,它正在对所有时间的评论计数进行排序。我希望能够突出显示最近流行的内容(就 cmets 而言)...
    • 我已经编辑了上面的答案,包括一周的截止日期
    • 我只是使用timedelta 信息快速尝试了这一点(请参阅原始帖子) - 乍一看,它正在做一些不同的事情,但 cmets 不再以最顶部的形式排序.. .我必须出去一会儿,但会尝试看看这里实际发生了什么变化......它似乎还不太正确。但我不确定它在做什么。可以肯定的是,它仍然返回了很多没有 cmets 的查询集(如果在过去 x # 天没有评论,我希望排除这些查询集)。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2021-10-05
    • 2016-03-23
    • 2021-11-30
    • 2020-05-04
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    • 2020-03-16
    相关资源
    最近更新 更多