Use facets always and auto hide empty item filters

pull/218/head
JensDiemer 2025-12-02 18:36:05 +01:00
rodzic 29df00e54a
commit cde20fcb65
7 zmienionych plików z 69 dodań i 46 usunięć

Wyświetl plik

@ -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/"

Wyświetl plik

@ -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 <PyInventory@jensdiemer.de>'

Wyświetl plik

@ -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})',
}

Wyświetl plik

@ -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 = (

Wyświetl plik

@ -50,13 +50,6 @@
<h2 id="changelist-filter-header">
Filter
</h2>
<div id="changelist-filter-extra-actions">
<h3>
<a class="viewlink" href="?_facets=True">
Show counts
</a>
</h3>
</div>
<details data-filter-title="Limit tree depth" open="">
<summary>
By Limit tree depth
@ -69,17 +62,17 @@
</li>
<li>
<a href="?level=1">
Only root
Only root (0)
</a>
</li>
<li>
<a href="?level=2">
Root + first sub
Root + first sub (0)
</a>
</li>
<li>
<a href="?level=3">
Root + first + second sub
Root + first + second sub (0)
</a>
</li>
</ul>

Wyświetl plik

@ -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=(
'<h1>Select Item to change</h1>',
'<a href="/admin/inventory/itemmodel/80dddef9-0000-0000-0000-000000000001/change/">'
'<strong>Item 1</strong></a>',
'<a href="/admin/inventory/itemmodel/80dddef9-0000-0000-0000-000000000002/change/">'
'<strong>Item 2</strong></a>',
'<a href="?category__id__exact=1">Category 1</a>',
'<a href="?category__id__exact=2">Category 2</a>',
),
)
self.assertEqual(
list(response.context_data['cl'].queryset.values_list('name', flat=True)), ['Item 1', 'Item 2']
)
self.assert_html_parts(
response,
parts=(
'<h1>Select Item to change</h1>',
'<a href="/admin/inventory/itemmodel/80dddef9-0000-0000-0000-000000000001/change/">'
'<strong>Item 1</strong></a>',
'<a href="/admin/inventory/itemmodel/80dddef9-0000-0000-0000-000000000002/change/">'
'<strong>Item 2</strong></a>',
'<a href="?category__id__exact=1">Category 1 (1)</a>',
'<a href="?category__id__exact=2">Category 2 (1)</a>',
),
)
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'])

Wyświetl plik

@ -338,13 +338,6 @@
<h2 id="changelist-filter-header">
Filter
</h2>
<div id="changelist-filter-extra-actions">
<h3>
<a class="viewlink" href="?_facets=True">
Show counts
</a>
</h3>
</div>
<details data-filter-title="Limit tree depth" open="">
<summary>
By Limit tree depth
@ -357,17 +350,17 @@
</li>
<li>
<a href="?level=1">
Only root
Only root (2)
</a>
</li>
<li>
<a href="?level=2">
Root + first sub
Root + first sub (6)
</a>
</li>
<li>
<a href="?level=3">
Root + first + second sub
Root + first + second sub (6)
</a>
</li>
</ul>