From cde20fcb6550f8f5ffaebde067198aef3fa3b5c5 Mon Sep 17 00:00:00 2001 From: JensDiemer Date: Tue, 2 Dec 2025 18:36:05 +0100 Subject: [PATCH] Use facets always and auto hide empty item filters --- README.md | 3 +- inventory/__init__.py | 2 +- inventory/admin/base.py | 36 +++++++++++++++++ inventory/admin/item.py | 9 +++-- ...location_empty_change_list_1.snapshot.html | 13 ++----- inventory_project/tests/test_admin_item.py | 39 +++++++++---------- ...dmin_item_auto_group_items_1.snapshot.html | 13 ++----- 7 files changed, 69 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index c478fbb..cd193f3 100644 --- a/README.md +++ b/README.md @@ -169,7 +169,8 @@ To make a new release, do this: [comment]: <> (✂✂✂ auto generated history start ✂✂✂) -* [**dev**](https://github.com/jedie/PyInventory/compare/v0.23.2...main) +* [v0.24.0](https://github.com/jedie/PyInventory/compare/v0.23.2...v0.24.0) + * 2025-12-02 - Use facets always and auto hide empty item filters * 2025-12-02 - Update requirements * [v0.23.2](https://github.com/jedie/PyInventory/compare/v0.23.1...v0.23.2) * 2025-11-28 - Fix logo if static path is not just "/static/" diff --git a/inventory/__init__.py b/inventory/__init__.py index 02048fe..ed4af1a 100644 --- a/inventory/__init__.py +++ b/inventory/__init__.py @@ -8,5 +8,5 @@ """ # See https://packaging.python.org/en/latest/specifications/version-specifiers/ -__version__ = '0.23.2' +__version__ = '0.24.0' __author__ = 'Jens Diemer ' diff --git a/inventory/admin/base.py b/inventory/admin/base.py index 0e14035..60f2f4b 100644 --- a/inventory/admin/base.py +++ b/inventory/admin/base.py @@ -19,6 +19,7 @@ class UserInlineMixin: class BaseUserAdmin(CompareVersionAdmin): + show_facets = admin.ShowFacets.ALWAYS form = OnlyUserRelationsModelForm def get_changelist(self, request, **kwargs): @@ -102,3 +103,38 @@ class LimitTreeDepthListFilter(admin.SimpleListFilter): if level: level = int(level) return queryset.filter(level__lte=level) + + +class NoneEmptyRelatedFieldListFilter(admin.RelatedOnlyFieldListFilter): + """ + Display only choices that results **not** in an empty change list! + """ + + def choices(self, changelist): + assert changelist.add_facets, f'Facets must be enabled to use {self.__class__.__name__}' + + facet_counts = self.get_facet_queryset(changelist) + yield { + 'selected': self.lookup_val is None and not self.lookup_val_isnull, + 'query_string': changelist.get_query_string(remove=[self.lookup_kwarg, self.lookup_kwarg_isnull]), + 'display': _('All'), + } + for pk_val, val in self.lookup_choices: + if count := facet_counts[f'{pk_val}__c']: + yield { + 'selected': self.lookup_val is not None and str(pk_val) in self.lookup_val, + 'query_string': changelist.get_query_string( + {self.lookup_kwarg: pk_val}, [self.lookup_kwarg_isnull] + ), + 'display': f'{val} ({count})', + } + + if self.include_empty_choice: + if count := facet_counts['__c']: + yield { + 'selected': bool(self.lookup_val_isnull), + 'query_string': changelist.get_query_string( + {self.lookup_kwarg_isnull: 'True'}, [self.lookup_kwarg] + ), + 'display': f'{self.empty_value_display} ({count})', + } diff --git a/inventory/admin/item.py b/inventory/admin/item.py index 96334ff..753a676 100644 --- a/inventory/admin/item.py +++ b/inventory/admin/item.py @@ -19,6 +19,7 @@ from inventory.admin.base import ( BaseImageModelInline, BaseUserAdmin, LimitTreeDepthListFilter, + NoneEmptyRelatedFieldListFilter, UserInlineMixin, ) from inventory.models import ItemLinkModel, ItemModel @@ -150,10 +151,10 @@ class ItemModelAdmin(ImportExportMixin, SortableAdminBase, BaseUserAdmin): list_filter = ( ('category', PersistentRelatedFieldListFilter), LimitTreeDepthListFilter, - ('kind', admin.RelatedOnlyFieldListFilter), - ('location', admin.RelatedOnlyFieldListFilter), - ('producer', admin.RelatedOnlyFieldListFilter), - ('tags', admin.RelatedOnlyFieldListFilter), + ('kind', NoneEmptyRelatedFieldListFilter), + ('location', NoneEmptyRelatedFieldListFilter), + ('producer', NoneEmptyRelatedFieldListFilter), + ('tags', NoneEmptyRelatedFieldListFilter), ) search_fields = ('name', 'description', 'kind__name', 'tags__name') fieldsets = ( diff --git a/inventory/tests/test_admin_location_empty_change_list_1.snapshot.html b/inventory/tests/test_admin_location_empty_change_list_1.snapshot.html index 8c3c697..2480836 100644 --- a/inventory/tests/test_admin_location_empty_change_list_1.snapshot.html +++ b/inventory/tests/test_admin_location_empty_change_list_1.snapshot.html @@ -50,13 +50,6 @@

Filter

-
By Limit tree depth @@ -69,17 +62,17 @@
  • - Only root + Only root (0)
  • - Root + first sub + Root + first sub (0)
  • - Root + first + second sub + Root + first + second sub (0)
  • diff --git a/inventory_project/tests/test_admin_item.py b/inventory_project/tests/test_admin_item.py index 1fdd6da..32ec281 100644 --- a/inventory_project/tests/test_admin_item.py +++ b/inventory_project/tests/test_admin_item.py @@ -265,28 +265,27 @@ class AdminTestCase(HtmlAssertionMixin, TestCase): ) with self.assertLogs('inventory.persistent_filters', level=logging.DEBUG) as logs: response = self.client.get(path='/admin/inventory/itemmodel/') - - self.assertEqual( - list(response.context_data['cl'].queryset.values_list('name', flat=True)), ['Item 1', 'Item 2'] - ) - self.assert_html_parts( - response, - parts=( - '

    Select Item to change

    ', - '' - 'Item 1', - '' - 'Item 2', - 'Category 1', - 'Category 2', - ), - ) + self.assertEqual( + list(response.context_data['cl'].queryset.values_list('name', flat=True)), ['Item 1', 'Item 2'] + ) + self.assert_html_parts( + response, + parts=( + '

    Select Item to change

    ', + '' + 'Item 1', + '' + 'Item 2', + 'Category 1 (1)', + 'Category 2 (1)', + ), + ) self.assertEqual( logs.output, [ 'DEBUG:inventory.persistent_filters:' "Restore None from 'persistent_parameter_1_inventory_itemmodel_category__id__exact'" - ], + ] * 3, # 3 times called because of facet counts :( ) with self.assertLogs('inventory.persistent_filters', level=logging.DEBUG) as logs: @@ -296,7 +295,7 @@ class AdminTestCase(HtmlAssertionMixin, TestCase): [ 'DEBUG:inventory.persistent_filters:' "Store '2' to 'persistent_parameter_1_inventory_itemmodel_category__id__exact'" - ], + ] * 3, # 3 times called because of facet counts :( ) # Only items from category 2: self.assertEqual(list(response.context_data['cl'].queryset.values_list('name', flat=True)), ['Item 2']) @@ -310,7 +309,7 @@ class AdminTestCase(HtmlAssertionMixin, TestCase): "DEBUG:inventory.persistent_filters:" "Restore '2' from 'persistent_parameter_1_inventory_itemmodel_category__id__exact'", "INFO:inventory.persistent_filters:Restore 'category' filter for itemmodel with '2'", - ], + ] * 3, # 3 times called because of facet counts :( ) # Only items from category 2: self.assertEqual(list(response.context_data['cl'].queryset.values_list('name', flat=True)), ['Item 2']) @@ -323,7 +322,7 @@ class AdminTestCase(HtmlAssertionMixin, TestCase): [ 'DEBUG:inventory.persistent_filters:' "Store '1' to 'persistent_parameter_1_inventory_itemmodel_category__id__exact'" - ], + ] * 3, # 3 times called because of facet counts :( ) # Only items from category 1: self.assertEqual(list(response.context_data['cl'].queryset.values_list('name', flat=True)), ['Item 1']) diff --git a/inventory_project/tests/test_admin_item_auto_group_items_1.snapshot.html b/inventory_project/tests/test_admin_item_auto_group_items_1.snapshot.html index 07f2e24..c2b394c 100644 --- a/inventory_project/tests/test_admin_item_auto_group_items_1.snapshot.html +++ b/inventory_project/tests/test_admin_item_auto_group_items_1.snapshot.html @@ -338,13 +338,6 @@

    Filter

    -
    By Limit tree depth @@ -357,17 +350,17 @@
  • - Only root + Only root (2)
  • - Root + first sub + Root + first sub (6)
  • - Root + first + second sub + Root + first + second sub (6)