2016-10-04 13 views
1

Я нашел этот фрагмент кода для повышения производительности больших таблиц базы данных запросов в списках администратора Django:Быстрее Django администратора Paginator: Не удается получить этот Джанго сниппет работать

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

Есть некоторые проблемы, связанные с ней при использовании это с Django 1.10, которые уже обсуждались в мой предыдущий вопрос здесь:

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

в частности, _count потребности в переименовывается в count и query_set - queryset. Вот короткая версия соответствующей части сниппета:

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

Я думаю, мы можем перетащить, что Paginator в Джанго 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