mirror of
https://github.com/netbox-community/netbox.git
synced 2025-12-11 19:09:36 -06:00
Fix registry pattern to use model identifiers as keys
Changed filterset registration to use model identifiers ('{app_label}.{model_name}')
as registry keys instead of form classes, matching NetBox's pattern for search indexes.
This commit is contained in:
parent
5664684530
commit
ee6a3a495b
@ -295,6 +295,7 @@ class SavedFilterFilterForm(SavedFiltersMixin, FilterForm):
|
|||||||
|
|
||||||
@register_filterset(TableConfigFilterSet)
|
@register_filterset(TableConfigFilterSet)
|
||||||
class TableConfigFilterForm(SavedFiltersMixin, FilterForm):
|
class TableConfigFilterForm(SavedFiltersMixin, FilterForm):
|
||||||
|
model = TableConfig
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
FieldSet('q', 'filter_id'),
|
FieldSet('q', 'filter_id'),
|
||||||
FieldSet('object_type_id', 'enabled', 'shared', 'weight', name=_('Attributes')),
|
FieldSet('object_type_id', 'enabled', 'shared', 'weight', name=_('Attributes')),
|
||||||
|
|||||||
@ -6,18 +6,14 @@ from .utils import *
|
|||||||
|
|
||||||
def register_filterset(filterset_class):
|
def register_filterset(filterset_class):
|
||||||
"""
|
"""
|
||||||
Decorator for registering a FilterForm -> FilterSet mapping.
|
Decorator for registering a FilterSet with the application registry.
|
||||||
|
|
||||||
Usage:
|
Uses model identifier as key to match search index pattern.
|
||||||
@register_filterset(DeviceFilterSet)
|
|
||||||
class DeviceFilterForm(NetBoxModelFilterSetForm):
|
|
||||||
...
|
|
||||||
|
|
||||||
Args:
|
|
||||||
filterset_class: The corresponding filterset class
|
|
||||||
"""
|
"""
|
||||||
def decorator(form_class):
|
def decorator(form_class):
|
||||||
from netbox.registry import registry
|
from netbox.registry import registry
|
||||||
registry['filtersets'][form_class] = filterset_class
|
model = filterset_class._meta.model
|
||||||
|
key = f'{model._meta.app_label}.{model._meta.model_name}'
|
||||||
|
registry['filtersets'][key] = filterset_class
|
||||||
return form_class
|
return form_class
|
||||||
return decorator
|
return decorator
|
||||||
|
|||||||
@ -176,14 +176,20 @@ class FilterModifierMixin:
|
|||||||
from utilities.forms.widgets import FilterModifierWidget
|
from utilities.forms.widgets import FilterModifierWidget
|
||||||
from netbox.registry import registry
|
from netbox.registry import registry
|
||||||
|
|
||||||
# Get the corresponding FilterSet if registered
|
model = getattr(self, 'model', None)
|
||||||
filterset_class = registry['filtersets'].get(self.__class__)
|
if model is None and hasattr(self, '_meta'):
|
||||||
|
model = getattr(self._meta, 'model', None)
|
||||||
|
|
||||||
|
filterset_class = None
|
||||||
|
if model:
|
||||||
|
key = f'{model._meta.app_label}.{model._meta.model_name}'
|
||||||
|
filterset_class = registry['filtersets'].get(key)
|
||||||
|
|
||||||
filterset = filterset_class() if filterset_class else None
|
filterset = filterset_class() if filterset_class else None
|
||||||
|
|
||||||
for field_name, field in self.fields.items():
|
for field_name, field in self.fields.items():
|
||||||
lookups = self._get_lookup_choices(field)
|
lookups = self._get_lookup_choices(field)
|
||||||
|
|
||||||
# Verify lookups against FilterSet if available
|
|
||||||
if filterset:
|
if filterset:
|
||||||
lookups = self._verify_lookups_with_filterset(field_name, lookups, filterset)
|
lookups = self._verify_lookups_with_filterset(field_name, lookups, filterset)
|
||||||
|
|
||||||
@ -198,24 +204,19 @@ class FilterModifierMixin:
|
|||||||
|
|
||||||
Returns an empty list for fields that should not be enhanced.
|
Returns an empty list for fields that should not be enhanced.
|
||||||
"""
|
"""
|
||||||
# Skip query/search fields
|
|
||||||
if isinstance(field, QueryField):
|
if isinstance(field, QueryField):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# Skip boolean fields (no benefit from modifiers)
|
|
||||||
if isinstance(field, (forms.BooleanField, forms.NullBooleanField)):
|
if isinstance(field, (forms.BooleanField, forms.NullBooleanField)):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# Skip API widget fields
|
|
||||||
if self._is_api_widget_field(field):
|
if self._is_api_widget_field(field):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# Walk up the MRO to find a known field type
|
|
||||||
for field_class in field.__class__.__mro__:
|
for field_class in field.__class__.__mro__:
|
||||||
if field_class in FORM_FIELD_LOOKUPS:
|
if field_class in FORM_FIELD_LOOKUPS:
|
||||||
return FORM_FIELD_LOOKUPS[field_class]
|
return FORM_FIELD_LOOKUPS[field_class]
|
||||||
|
|
||||||
# Unknown field type - return empty list (no enhancement)
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def _verify_lookups_with_filterset(self, field_name, lookups, filterset):
|
def _verify_lookups_with_filterset(self, field_name, lookups, filterset):
|
||||||
@ -223,13 +224,11 @@ class FilterModifierMixin:
|
|||||||
verified_lookups = []
|
verified_lookups = []
|
||||||
|
|
||||||
for lookup_code, lookup_label in lookups:
|
for lookup_code, lookup_label in lookups:
|
||||||
# Handle special empty_true/false codes that map to __empty
|
|
||||||
if lookup_code in (MODIFIER_EMPTY_TRUE, MODIFIER_EMPTY_FALSE):
|
if lookup_code in (MODIFIER_EMPTY_TRUE, MODIFIER_EMPTY_FALSE):
|
||||||
filter_key = f'{field_name}__empty'
|
filter_key = f'{field_name}__empty'
|
||||||
else:
|
else:
|
||||||
filter_key = f'{field_name}__{lookup_code}' if lookup_code != 'exact' else field_name
|
filter_key = f'{field_name}__{lookup_code}' if lookup_code != 'exact' else field_name
|
||||||
|
|
||||||
# Check if this filter exists in the FilterSet
|
|
||||||
if filter_key in filterset.filters:
|
if filter_key in filterset.filters:
|
||||||
verified_lookups.append((lookup_code, lookup_label))
|
verified_lookups.append((lookup_code, lookup_label))
|
||||||
|
|
||||||
@ -237,11 +236,9 @@ class FilterModifierMixin:
|
|||||||
|
|
||||||
def _is_api_widget_field(self, field):
|
def _is_api_widget_field(self, field):
|
||||||
"""Check if a field uses an API-based widget."""
|
"""Check if a field uses an API-based widget."""
|
||||||
# Check field class name
|
|
||||||
if 'Dynamic' in field.__class__.__name__:
|
if 'Dynamic' in field.__class__.__name__:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Check widget attributes for API-related data
|
|
||||||
if hasattr(field.widget, 'attrs') and field.widget.attrs:
|
if hasattr(field.widget, 'attrs') and field.widget.attrs:
|
||||||
api_attrs = ['data-url', 'data-api-url', 'data-static-params']
|
api_attrs = ['data-url', 'data-api-url', 'data-static-params']
|
||||||
if any(attr in field.widget.attrs for attr in api_attrs):
|
if any(attr in field.widget.attrs for attr in api_attrs):
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user