diff options
| author | Thomas Chaumeny <thomas.chaumeny@polyconseil.fr> | 2014-09-22 18:46:43 +0200 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2014-09-26 12:12:40 -0400 |
| commit | 17557d068c43bd61cdc6c18caf250ffa469414a1 (patch) | |
| tree | f404b1f0c5f03bcdb14d39282ed6ec686085909a | |
| parent | d1ca70110f49f0be90206c8da516ac16aebc8c75 (diff) | |
Fixed #8408 -- Added ModelAdmin.show_full_result_count to avoid COUNT() query.
Thanks lidaobing for the suggestion.
| -rw-r--r-- | django/contrib/admin/options.py | 1 | ||||
| -rw-r--r-- | django/contrib/admin/templates/admin/change_list.html | 4 | ||||
| -rw-r--r-- | django/contrib/admin/templates/admin/search_form.html | 2 | ||||
| -rw-r--r-- | django/contrib/admin/views/main.py | 13 | ||||
| -rw-r--r-- | docs/ref/contrib/admin/index.txt | 13 | ||||
| -rw-r--r-- | docs/releases/1.8.txt | 4 | ||||
| -rw-r--r-- | tests/admin_views/admin.py | 1 | ||||
| -rw-r--r-- | tests/admin_views/tests.py | 19 |
8 files changed, 50 insertions, 7 deletions
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index f7fce09ddc..6edae7a5c5 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -110,6 +110,7 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)): readonly_fields = () ordering = None view_on_site = True + show_full_result_count = True # Validation of ModelAdmin definitions # Old, deprecated style: diff --git a/django/contrib/admin/templates/admin/change_list.html b/django/contrib/admin/templates/admin/change_list.html index ca0080e3be..e99b1e0a6e 100644 --- a/django/contrib/admin/templates/admin/change_list.html +++ b/django/contrib/admin/templates/admin/change_list.html @@ -87,9 +87,9 @@ {% endif %} {% block result_list %} - {% if action_form and actions_on_top and cl.full_result_count %}{% admin_actions %}{% endif %} + {% if action_form and actions_on_top and cl.show_admin_actions %}{% admin_actions %}{% endif %} {% result_list cl %} - {% if action_form and actions_on_bottom and cl.full_result_count %}{% admin_actions %}{% endif %} + {% if action_form and actions_on_bottom and cl.show_admin_actions %}{% admin_actions %}{% endif %} {% endblock %} {% block pagination %}{% pagination cl %}{% endblock %} </form> diff --git a/django/contrib/admin/templates/admin/search_form.html b/django/contrib/admin/templates/admin/search_form.html index c9b626d18f..4cc24604f7 100644 --- a/django/contrib/admin/templates/admin/search_form.html +++ b/django/contrib/admin/templates/admin/search_form.html @@ -6,7 +6,7 @@ <input type="text" size="40" name="{{ search_var }}" value="{{ cl.query }}" id="searchbar" /> <input type="submit" value="{% trans 'Search' %}" /> {% if show_result_count %} - <span class="small quiet">{% blocktrans count counter=cl.result_count %}{{ counter }} result{% plural %}{{ counter }} results{% endblocktrans %} (<a href="?{% if cl.is_popup %}_popup=1{% endif %}">{% blocktrans with full_result_count=cl.full_result_count %}{{ full_result_count }} total{% endblocktrans %}</a>)</span> + <span class="small quiet">{% blocktrans count counter=cl.result_count %}{{ counter }} result{% plural %}{{ counter }} results{% endblocktrans %} (<a href="?{% if cl.is_popup %}_popup=1{% endif %}">{% if cl.show_full_result_count %}{% blocktrans with full_result_count=cl.full_result_count %}{{ full_result_count }} total{% endblocktrans %}{% else %}{% trans "Show all" %}{% endif %}</a>)</span> {% endif %} {% for pair in cl.params.items %} {% ifnotequal pair.0 search_var %}<input type="hidden" name="{{ pair.0 }}" value="{{ pair.1 }}"/>{% endifnotequal %} diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py index 1f42310f8e..1fcc774657 100644 --- a/django/contrib/admin/views/main.py +++ b/django/contrib/admin/views/main.py @@ -177,10 +177,13 @@ class ChangeList(object): # Perform a slight optimization: # full_result_count is equal to paginator.count if no filters # were applied - if self.get_filters_params() or self.params.get(SEARCH_VAR): - full_result_count = self.root_queryset.count() + if self.model_admin.show_full_result_count: + if self.get_filters_params() or self.params.get(SEARCH_VAR): + full_result_count = self.root_queryset.count() + else: + full_result_count = result_count else: - full_result_count = result_count + full_result_count = None can_show_all = result_count <= self.list_max_show_all multi_page = result_count > self.list_per_page @@ -194,6 +197,10 @@ class ChangeList(object): raise IncorrectLookupParameters self.result_count = result_count + self.show_full_result_count = self.model_admin.show_full_result_count + # Admin actions are shown if there is at least one entry + # or if entries are not counted because show_full_result_count is disabled + self.show_admin_actions = self.show_full_result_count or bool(full_result_count) self.full_result_count = full_result_count self.result_list = result_list self.can_show_all = can_show_all diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index ca55df3ce7..bf34fa47f1 100644 --- a/docs/ref/contrib/admin/index.txt +++ b/docs/ref/contrib/admin/index.txt @@ -1160,6 +1160,19 @@ subclass:: :meth:`ModelAdmin.get_search_results` to provide additional or alternate search behavior. +.. attribute:: ModelAdmin.show_full_result_count + + .. versionadded:: 1.8 + + Set ``show_full_result_count`` to control whether the full count of objects + should be displayed on a filtered admin page (e.g. ``99 results (103 total)``). + If this option is set to ``False``, a text like ``99 results (Show all)`` + is displayed instead. + + The default of ``show_full_result_count=True`` generates a query to perform + a full count on the table which can be expensive if the table contains a + large number of rows. + .. attribute:: ModelAdmin.view_on_site .. versionadded:: 1.7 diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt index 5c28840c50..c77b40a6a3 100644 --- a/docs/releases/1.8.txt +++ b/docs/releases/1.8.txt @@ -72,6 +72,10 @@ Minor features <django.contrib.admin.AdminSite.site_url>` in order to display a link to the front-end site. +* You can now specify :attr:`ModelAdmin.show_full_result_count + <django.contrib.admin.ModelAdmin.show_full_result_count>` to control whether + or not the full count of objects should be displayed on a filtered admin page. + :mod:`django.contrib.auth` ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py index 077d64b50d..7caca29c7b 100644 --- a/tests/admin_views/admin.py +++ b/tests/admin_views/admin.py @@ -327,6 +327,7 @@ class LanguageAdmin(admin.ModelAdmin): class RecommendationAdmin(admin.ModelAdmin): + show_full_result_count = False search_fields = ('=titletranslation__text', '=recommender__titletranslation__text',) diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index c9b946ac5e..88539d4684 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -2474,11 +2474,28 @@ class AdminSearchTest(TestCase): """ Test presence of reset link in search bar ("1 result (_x total_)"). """ - response = self.client.get('/test_admin/admin/admin_views/person/?q=Gui') + # 1 query for session + 1 for fetching user + # + 1 for filtered result + 1 for filtered count + # + 1 for total count + with self.assertNumQueries(5): + response = self.client.get('/test_admin/admin/admin_views/person/?q=Gui') self.assertContains(response, """<span class="small quiet">1 result (<a href="?">3 total</a>)</span>""", html=True) + def test_no_total_count(self): + """ + #8408 -- "Show all" should be displayed instead of the total count if + ModelAdmin.show_full_result_count is False. + """ + # 1 query for session + 1 for fetching user + # + 1 for filtered result + 1 for filtered count + with self.assertNumQueries(4): + response = self.client.get('/test_admin/admin/admin_views/recommendation/?q=bar') + self.assertContains(response, + """<span class="small quiet">1 result (<a href="?">Show all</a>)</span>""", + html=True) + @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',), ROOT_URLCONF="admin_views.urls") |
