2016-10-04 24 views
1

我發現這個片斷爲提高大型數據庫表查詢的Django管理列表的效果:使用時更快Django管理分頁程序:不能得到這個Django的片段工作

https://djangosnippets.org/snippets/2593/

有關於它的一些問題它使用Django 1.10,這是在我剛纔的問題已經在這裏討論:

How to speed up Django's admin pages with PostgreSQL count estimates?

特別是_count需要重命名爲countquery_setqueryset。以下是摘錄相關部分的簡短版本:

from django.core.paginator import Paginator 
from django.core.cache import cache 
class FasterAdminPaginator(Paginator): 
    def _get_count(self): 
     if self.count is None: 
      try: 
       key = "adm:{0}:count".format(hash(self.object_list.query.__str__())) 
       self.count = cache.get(key, -1); 
       if self.count == -1 : 
        if not self.object_list.query.where: 
         # estimates COUNT: https://djangosnippets.org/snippets/2593/ 
         cursor = connection.cursor() 
         cursor.execute("SELECT reltuples FROM pg_class WHERE relname = %s", 
          [self.object_list.query.model._meta.db_table]) 
         self.count = int(cursor.fetchone()[0]) 
        else : 
         self.count = self.object_list.count() 
        cache.set(key, self.count, 3600) 
      except: 
       # AttributeError if object_list has no count() method. 
       self.count = len(self.object_list) 
     return self.count 
    count = property(_get_count) 

問題是,我仍然無法使其工作。當前錯誤日誌摘錄:

maximum recursion depth exceeded while calling a Python object 
... 
result_count = paginator.count 
... 
if self.count is None: 

不知道如何讓代碼段工作。

回答

2

我認爲我們可以拖動分頁程序到Django的1.10世界是這樣的(hopefullly不踢和尖叫):

from django.core.paginator import Paginator 
from django.core.cache import cache 
from django.utils.functional import cached_property 
from django.db import connection 

class FasterAdminPaginator(Paginator): 
    @cached_property 
    def count(self): 
     try: 
      if not self.object_list.query.where: 
       # estimates COUNT: https://djangosnippets.org/snippets/2593/ 
       cursor = connection.cursor() 
       cursor.execute("SELECT reltuples FROM pg_class WHERE relname = %s", 
        [self.object_list.query.model._meta.db_table]) 
       print 'Using the reltuples' 

       ret = int(cursor.fetchone()[0]) 
      else : 
       return self.object_list.count() 
     except : 
      import traceback 
      traceback.print_exc() 
      # AttributeError if object_list has no count() method. 
      return len(self.object_list) 

Thakns到cached_property原片段中使用廣泛緩存代碼不再需要。爲了完整起見,這是django.core.paginator.Paginator的相關部分看起來像

@cached_property 
def count(self): 
    """ 
    Returns the total number of objects, across all pages. 
    """ 
    try: 
     return self.object_list.count() 
    except (AttributeError, TypeError): 
     # AttributeError if object_list has no count() method. 
     # TypeError if object_list.count() requires arguments 
     # (i.e. is of type list). 
     return len(self.object_list) 
+0

工程就像一個魅力。謝謝。有趣的是,我基本上同時在片段中發現了這個問題。由於try-except,我只是沒有注意到'connection'的缺失導入。 –

+0

是的,這對我來說是一件非常糟糕的事情。感謝您將答案標記爲正確,即使您自己做出了同步發現 – e4c5