【问题标题】:django pagination and RawQuerySetdjango 分页和 RawQuerySet
【发布时间】:2011-07-06 09:30:26
【问题描述】:

有没有办法使用 django 的内置分页对 rawqueryset 进行分页? 当我将它转换为列表时,它会在我的脸上抛出一个错误 ...TypeError: expected string or Unicode object, NoneType found。有没有办法解决这个问题?

【问题讨论】:

    标签: python django django-pagination


    【解决方案1】:

    我设法使用以下方法实现了它:

    paginator = Paginator(files, 12)
    paginator._count = len(list(files))
    

    django.core.paginator.py 中的代码:

    • 检查是否设置了 _count
    • 如果没有,则尝试运行不存在的 .count()
    • 如果没有,则尝试普通 len

    raw_queryset 上的 len 不起作用,但将实际的分页器对象转换为列表可以在 Django 1.3 中为我找到

    【讨论】:

    • 显然 len(list(files)) 对于大型原始查询集的内存效率非常低。鉴于您知道已运行的查询,您可以使用 COUNT(*) 运行另一个查询,并将其分配给 paginator._count,只要结果的数量不会在每个查询之间发生变化。或者,如果查询结果不断变化,不同的 DBMS 有方法可以在查询的每一行中嵌入总行数。
    • 不幸的是,RawQuerySet.__getitem__() 无论如何都会调用 list(self) - 所以一旦你调用 paginator.get_page(),它就会完全加载到内存中。为避免这种情况,我认为您必须继承 RawQuerySet,并确保您的原始 SQL 具有 LIMIT/OFFSET - 即使这样,您也会丢失普通查询集的结果缓存,因此访问 qs[0] 两次将命中数据库两次。
    • 是的,它会命中两次。我也是自己发现的。因此,最好为该原始查询集编写非常有效的 sql,而不是将原始查询集传递给 len(list()) 和分页器,而是首先通过循环来评估查询集。像 l = [item for item in queryset] 然后将该 l 传递给分页器和 len(l)。这只会给您一个数据库调用。
    【解决方案2】:

    您可以为 RawQuerySet 对象手动设置属性计数:

    items = Item.objects.raw("select * from appitem_item")
    
    def items_count():
        cursor = connection.cursor()
        cursor.execute("select count(*) from appitem_item")
        row = cursor.fetchone()
        return row[0]
    
    items.count = items_count
    

    对于@Rockallite

    >>> class A():
    ...    def b(self):
    ...        print 'from b'
    ... 
    >>> 
    >>> (A()).b()
    from b
    >>> def c():
    ...    print 'from c'
    ... 
    >>> a = A()
    >>> a.b = c
    >>> a.b()
    from c
    

    【讨论】:

    • django.core.paginator.Paginator 寻找count() 方法。所以设置count属性是行不通的。
    • 为什么,你测试了吗?当然,这是一个 hack,但我使用了它。我的意思是在python中你可以用另一种方法替换一种方法。
    • Rockallite,我添加代码是为了说明这个 hack 是如何工作的
    【解决方案3】:
    qs.filter(**pfilter).distinct().extra(select={'test': 'COALESCE(`psearch_program`.`eu_price`, 999999999)'}).extra(order_by=['test'])
    

    【讨论】:

    • -1:解释正在做什么,与什么兼容等。
    猜你喜欢
    • 2011-01-20
    • 1970-01-01
    • 2016-02-16
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 2014-12-29
    相关资源
    最近更新 更多