Django过滤、分页和注释分页结果

2024-10-01 13:29:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我有objectreports和ReportSubscriber,我想计算报表的订阅数。在

一个解决方案是注释。我有很多报告,所以注释所有的报告需要大约6秒钟,所以我想也许最好在分页后进行注释:

filter_search = ReportFilter(request.GET, queryset=Report.objects.filter(
        created_at__gt=start_date,
        created_at__lte=end_date,
        is_confirmed__exact=True,
    ).annotate(sub_count=Count("reportsubscriber")).order_by('-sub_count'))

paginator = Paginator(filter_search, 20)

result = paginator.page(1).object_list.annotate(
                sub_count=Count("reportsubscriber"))

它工作了,但花费了相同的时间,当我检查查询时,它实际上仍然遍历report_subscriber表中的所有行。所以我试着用.extra()

^{pr2}$

但这还是没用。我得到了所有报表的静态订阅数。我错过了什么,也许还有更好的方法来完成这个任务?谢谢


Tags: searchdate报表报告count解决方案filterat
3条回答

好的,明白了。我选错桌子了。在

所以我更改了.extra(),现在只计算每页的数量:

result = filter_search.qs.extra(
            select={
                'sub_count': 'SELECT COUNT(*) FROM report_subscribers \
                             WHERE report_subscribers.report_id = reports.id\
                             AND report_subscribers.report_id IN %s \
                            ' % "(%s)" % ",".join([str(r.id) for r in paged_reports.object_list])

            }
        )

但现在我不能按sub_count排序,因为我没有所有的值。好吧,也许没有任何其他方法可以不计算所有计数或实际将计数存储在数据库中

这就是我如何使用Paginator进行筛选和基于类的视图:

from django.core.paginator import Paginator, EmptyPage, InvalidPage

class BaseTemplateView(TemplateView):
    """
    Abstract View to populate NavBar context
    """
    def get_context_data(self, **kwargs):
        context = super(BaseTemplateView, self).get_context_data(**kwargs)
        context['ideas'] = Idea.objects.all()
        return context

class IdeaView(BaseTemplateView):

    template_name = 'products/idea.html'

    def get(self, request, *args, **kwargs):
        ideas = Idea.objects.all()
        idea = get_object_or_404(Idea, slug=kwargs['slug'])
        products = Product.objects.filter(ideas=idea)
        products_list = products
        paginator = Paginator(products_list, 12)
        try:
            page = int(request.GET.get('page', '1'))
        except:
            page = 1

        try:
            products = paginator.page(page)
        except(EmptyPage, InvalidPage):
            products = paginator.page(paginator.num_pages)

        return render_to_response(self.template_name,
            {'ideas': ideas, 'idea': idea, 'products': products},
            context_instance=RequestContext(request))

我不能给你一个明确的答案,我相信你的问题是,即使分页,你的整个查询也必须执行,这样分页器才能知道有多少页。我认为最好在分页之前去掉注释:

filter_search = ReportFilter(request.GET, queryset=Report.objects.filter(
        created_at__gt=start_date,
        created_at__lte=end_date,
        is_confirmed__exact=True,
    ).order_by('-sub_count'))

paginator = Paginator(filter_search, 20)

result = paginator.page(1).object_list.annotate(
                sub_count=Count("reportsubscriber"))

我相信从您的例子来看,object_list是一个可以annotate的查询集,但是如果它只是一个list的对象,那么您可以用如下内容注释每个结果页:

^{pr2}$

但这一切都是在黑暗中进行的。您所做的一切看起来都太疯狂了,所以除非您的数据集很大,否则我只能想象您的问题是一个索引错误的查询。您确实需要分析正在生成的实际查询。对于给定的start_dateend_data,可以通过从项目Django shell中执行来获取SQL:

Report.objects.filter(
        created_at__gt=start_date,
        created_at__lte=end_date,
        is_confirmed__exact=True,
    ).order_by('-sub_count').query

然后使用EXPLAIN从数据库的PSQL命令行运行相同的查询。你得读一点书,弄清楚如何解释结果。在

相关问题 更多 >