django admin tables with large postgre sql tables

Django admin page likes to do counts on tables in its change list view so that it can draw a pretty pagination widget at the bottom. These two facts make for a miserable admin experience when you have more than a handful of rows in your database. One visitor to the admin site will at best have to wait for a while before the page loads, several will most likely bring the database server to its knees. Here is patch for Posgre SQL based on Django admin with large tables article.

Add this code to admin.py:


from django.db.models.query import QuerySet
from django.db import connections

class ApproxCountQuerySet(QuerySet):
    '''Counting all rows is very expensive on large tables. This
    is a replacement for QuerySet that returns an approximation if count()
    is called with no additional constraints. In all other cases it should
    behave exactly as QuerySet.'''

    def count(self):
        """
        Performs a SELECT COUNT() and returns the number of records as an
        integer.

        If the QuerySet is already fully cached this simply returns the length
        of the cached results set to avoid multiple SELECT COUNT(*) calls.
        """
        if self._result_cache is not None and not self._iter:
            return len(self._result_cache)

        query = self.query

        if (not query.where) and \
                query.high_mark is None and \
                query.low_mark == 0 and \
                (not query.select) and \
                (not query.group_by) and \
                (not query.having) and \
                (not query.distinct):
            # If query has no constraints, we would be simply doing
            # "SELECT COUNT(*) FROM foo". Monkey patch so the we
            # get an approximation instead.
            cursor = connections[self.db].cursor()
            cursor.execute("SELECT reltuples  FROM pg_class r WHERE relkind = 'r' AND relname = '%s'" % self.model._meta.db_table)
            
            return int(cursor.fetchall()[0][0])
        else:
            return self.query.get_count(using=self.db)

class FooAdmin(admin.ModelAdmin): 
	def queryset(self, request): 
		qs = super(FooAdmin, self).queryset(request) 
		return qs._clone(klass=ApproxCountQuerySet) 

Where FooAdmin your model admin class

Other links: Counting rows in postgresql

Login Sign up

Login

Tag cloud

count count all django django admin feedparser libxml2dom linux mysql parser payway python pyunit pyvkapi qiwi return sniffer sockets ssh ssh tunnel sublime text tdd tehtv templatetags ubuntu unittest webmoney X11 аргументы биллинг видео видеоурок видео уроки вконтакте возврат диаграмма диаграмма стека заметки инструкция комментарии композиция логические операторы мышка образование обучение операторы параметры функции парсинг переменная переменные питон платежи поток выполнения преобразование типов программирование проекты процессинг разработка разработкаразработка рекурсия сеть скрипт сниффер сокеты стек стоки тестирование тип тип данных типы урок уроки условия функция
free counters