使用两列对查询集进行排序,然后有效地进行分页

时间:2017-11-26 22:43:46

标签: python django sql-order-by django-pagination

我想要使用其中一个列排序queryset,例如date1,如果date1的值为None则使用另一列date2用于排序,如果date2也是None,则使用datetime.max。所以,这就是我想出的:

queryset = sorted(queryset, key= lambda row: row.date1 if row.date1 else row.date2 if row.date2 else datetime.max)

然后进行分页(在一个页面中说20个)我发送回上一个请求的最后一条记录的id并使用它来获取接下来的20个项目(因为现在排序ID之后)以随机顺序)。此外,用户可以删除这些条目,因此,使用Paginator.page并仅在请求中获取连续页面将无法正常工作。

这就是我找到lastRecord获取下一个20的索引:

lastRecordIndex = next(i for (i, d) in enumerate(queryset) if d.id == lastRecord)
queryset = queryset[lastRecordIndex+1: lastRecordIndex+20+1]

所以,问题是这种方法有效,但速度太慢。我能做些什么更好的事情吗?使用原始查询或django中的其他内容?

1 个答案:

答案 0 :(得分:1)

您可以使用conditional expression创建查询。像这样:

queryset = MyModel.objects.all()\
        .annotate(date3=Case(
                When(date1__isnull=False, then='date1'),
                When(date2__isnull=False, then='date2'),
                default=Value(datetime.date.max), 
                output_field=DateField()
            )
        )\
        .order_by('date3')

但要小心谨慎;只有在date1date2设置为 null 时才能使用此功能。它不适用于空白。并且它也不会超级快,因为查询集中的每个对象都将被注释,但至少代码更清晰:)