2011-03-01 45 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