Skip to content

Instantly share code, notes, and snippets.

@ketanbhatt
Last active February 25, 2022 11:08
Show Gist options
  • Save ketanbhatt/846644beb59457485a3decd8dec6a4c4 to your computer and use it in GitHub Desktop.
Save ketanbhatt/846644beb59457485a3decd8dec6a4c4 to your computer and use it in GitHub Desktop.
from django.contrib.admin import ModelAdmin
class MyTableAdmin(ModelAdmin):
...
paginator = LargeTablePaginator
...
from django.core.paginator import Paginator
class LargeTablePaginator(Paginator):
"""
Warning: Postgresql only hack
Overrides the count method of QuerySet objects to get an estimate instead of actual count when not filtered.
However, this estimate can be stale and hence not fit for situations where the count of objects actually matter.
"""
def _get_count(self):
if getattr(self, '_count', None) is not None:
return self._count
query = self.object_list.query
if not query.where:
try:
cursor = connection.cursor()
cursor.execute("SELECT reltuples FROM pg_class WHERE relname = %s",
[query.model._meta.db_table])
self._count = int(cursor.fetchone()[0])
except:
self._count = super(LargeTablePaginator, self)._get_count()
else:
self._count = super(LargeTablePaginator, self)._get_count()
return self._count
count = property(_get_count)
@chachra
Copy link

chachra commented Oct 11, 2018

Think this is needed.
from django.db import connection

@Kub-AT
Copy link

Kub-AT commented Mar 4, 2019

UPDATE: The code has been updated to be compatible with Django ≤ 1.11

But in 1.11.x there is not Paginator._get_count method/property. (Removed in 1.10a1)

So for 1.10 >= it should be

class LargeTablePaginator(Paginator):
    @functional.cached_property
    def count(self):
        query = self.object_list.query
        if not query.where:
            try:
                cursor = connection.cursor()
                cursor.execute('SELECT reltuples FROM pg_class WHERE relname = %s', [query.model._meta.db_table])
                return int(cursor.fetchone()[0])
            except Exception as e:  # noqa
                logger.warning(e)

        return super().count

@jeffreybrowning
Copy link

jeffreybrowning commented Mar 28, 2019

^ Missing imports:

from django.utils.functional import cached_property
from django.db import connection
import logging

setup logger from logging as needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment