2011-03-01 83 views
9

有没有一种方法来分页使用Django的内置分页rawqueryset? 当我将它转换为列表时,它会在我的脸上引发错误... TypeError:预期的字符串或Unicode对象,找不到类型。有没有解决的办法?Django分页和RawQuerySet

回答

14

我设法使用下面的实现它:在django.core.paginator.py

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

代码:

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

len个在raw_queryset不工作,但实际的分页程序对象转换为一个列表在Django的作品给我找1.3

+7

显然LEN(名单(文件))是非常低效的内存对于大型原始查询集。假设您知道运行的查询,则可以使用COUNT(*)运行另一个查询,并将其分配给paginator._count,只要每个查询之间的结果数量不会发生变化。 另外,如果查询结果不断变化,则不同的DBMS可以在查询的每一行中嵌入总行数。 – Chris 2011-04-07 13:17:32

+0

不幸的是,无论如何,[RawQuerySet .__ getitem__()](https://code.djangoproject.com/browser/django/trunk/django/db/models/query.py?rev=17381#L1517)调用list(self)所以一旦你调用'paginator.get_page()',它就会被完全加载到内存中。为了避免这种情况,我认为你必须继承RawQuerySet,并确保你的原始SQL有LIMIT/OFFSET - 即使这样,你将失去一个正常查询集的结果缓存,因此两次访问qs [0]会两次击中DB。 – AdamKG 2012-01-20 18:59:07

+0

是的,它会击中两次。我也为自己发现了它。因此,最好的办法是为原始查询集编写非常高效的SQL,而不是将原始查询集传递给len(list())和paginator,首先通过循环查询查询集。就像l = [itemset中item的项目],然后将该l传递给paginator和len(l)。这只给你一个数据库调用。 – 2013-12-18 13:06:42

4

您可以设置属性手动计数您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 
+0

django.core.paginator.Paginator查找'count()'方法。所以设置'count'属性不起作用。 – Rockallite 2013-12-03 08:51:58

+0

为什么,你测试了吗?当然,这是一个黑客,但我用它。我的意思是在python中你可以用另一种方法替换一种方法。 – 2014-02-26 18:55:40

+0

Rockallite,我添加了代码以说明这个破解如何工作 – 2014-02-26 18:57:57

-2
qs.filter(**pfilter).distinct().extra(select={'test': 'COALESCE(`psearch_program`.`eu_price`, 999999999)'}).extra(order_by=['test']) 
+0

-1:解释正在做什么以及与什么兼容等。 – 2014-07-14 12:33:59