How to speed up Django's admin pages with Post

2019-07-07 07:29发布

问题:

It's quite known that Django's admin list views are getting rather slow when the database tables have lots of rows. That's because the Django paginator uses by default a (slow) PostgreSQL COUNT query.

As estimate would be fine for us and it's much faster, e.g.: SELECT reltuples FROM pg_class WHERE relname = "my_table_name"

There is snippet available to fix this issue, but it's unclear to me how to actually use it: https://djangosnippets.org/snippets/2593/

Also, the snippet is not supposed to work on filtered results. That's because the estimate count as shown above doesn't work here. Is there another way to speed up filtered list views in Django admin pages?

回答1:

You use it by overriding the ModelAdmin.paginator

The paginator class to be used for pagination. By default, django.core.paginator.Paginator is used. If the custom paginator class doesn’t have the same constructor interface as django.core.paginator.Paginator, you will also need to provide an implementation for ModelAdmin.get_paginator().

class MyModelAdmin(admin.ModelAdmin):
    paginator = CachingPaginator

Bonus feature: I have improved on that snippet to create one that works with and without filters: https://gist.github.com/e4c5/6852723 it gets the count from rel_tuples when possible but when a filter is used the count is saved to the cache.

Update 1:
The problem with the original snippet reffered to in your answer is due to this change announced in the 1.6 release notes: https://docs.djangoproject.com/en/1.10/releases/1.6/#get-query-set-and-similar-methods-renamed-to-get-queryset

It's a trivial fix.

update 2
My improvement to the original snippet has been made some what obsolete by the _count propert being renamed to count and also it being decorated as a cached_property



回答2:

There is an option to choose the desired behaviour since Django 1.8: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/#django.contrib.admin.ModelAdmin.show_full_result_count

Example:

class MyModelAdmin(admin.ModelAdmin):
    show_full_result_count = False