Skip to content

Commit 9b7c3e8

Browse files
committed
feat(segment-filters): add has_type_specific_data filter and simplify path data filtering
- filtersets/segment.py: - change has_path_data from MultipleChoiceFilter to ChoiceFilter - add new has_type_specific_data ChoiceFilter with custom method - simplify _has_path_data logic to handle single choice values - implement _has_type_specific_data to check for null or empty type_specific_data - forms/segment.py: - change has_path_data to ChoiceField with Any option - add new has_type_specific_data ChoiceField with Any/Yes/No options - include new field in Basic fieldset - graphql/filters.py: - remove debug logging line from has_path_data filter
1 parent 996fe96 commit 9b7c3e8

File tree

3 files changed

+46
-26
lines changed

3 files changed

+46
-26
lines changed

cesnet_service_path_plugin/filtersets/segment.py

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from extras.filters import TagFilter
77
from netbox.filtersets import NetBoxModelFilterSet
88

9+
910
from cesnet_service_path_plugin.models import Segment
1011
from cesnet_service_path_plugin.models.custom_choices import StatusChoices
1112
from cesnet_service_path_plugin.models.segment_types import SegmentTypeChoices
@@ -86,7 +87,7 @@ class SegmentFilterSet(NetBoxModelFilterSet):
8687
)
8788

8889
# Path data filter
89-
has_path_data = django_filters.MultipleChoiceFilter(
90+
has_path_data = django_filters.ChoiceFilter(
9091
choices=[
9192
(True, "Yes"),
9293
(False, "No"),
@@ -95,6 +96,16 @@ class SegmentFilterSet(NetBoxModelFilterSet):
9596
label="Has Path Data",
9697
)
9798

99+
# Type specific data filter
100+
has_type_specific_data = django_filters.ChoiceFilter(
101+
choices=[
102+
(True, "Yes"),
103+
(False, "No"),
104+
],
105+
method="_has_type_specific_data",
106+
label="Has Type Specific Data",
107+
)
108+
98109
# =============================================================================
99110
# TYPE-SPECIFIC FILTERS
100111
# =============================================================================
@@ -218,6 +229,7 @@ class Meta:
218229
"site_b",
219230
"location_b",
220231
"has_path_data",
232+
"has_type_specific_data",
221233
]
222234

223235
def _at_any_site(self, queryset, name, value):
@@ -239,38 +251,33 @@ def _at_any_location(self, queryset, name, value):
239251
def _has_path_data(self, queryset, name, value):
240252
"""
241253
Filter segments based on whether they have path data or not
242-
243-
Args:
244-
value: List of selected values from choices
245-
[True] - show only segments with path data
246-
[False] - show only segments without path data
247-
[True, False] - show all segments (both with and without)
248-
[] - show all segments (nothing selected)
249254
"""
250-
if not value:
255+
if value in (None, "", []):
251256
# Nothing selected, show all segments
252257
return queryset
253258

254-
# Convert string values to boolean (django-filter sometimes passes strings)
255-
bool_values = []
256-
for v in value:
257-
if v is True or v == "True" or v:
258-
bool_values.append(True)
259-
elif v is False or v == "False" or not v:
260-
bool_values.append(False)
259+
has_data = value in [True, "True", "true", "1"]
261260

262-
if True in bool_values and False in bool_values:
263-
# Both selected, show all segments
264-
return queryset
265-
elif True in bool_values:
261+
if has_data:
266262
# Only "Yes" selected, show segments with path data
267263
return queryset.filter(path_geometry__isnull=False)
268-
elif False in bool_values:
264+
else:
269265
# Only "No" selected, show segments without path data
270266
return queryset.filter(path_geometry__isnull=True)
267+
268+
def _has_type_specific_data(self, queryset, name, value):
269+
"""Filter segments by whether they have type-specific data"""
270+
if value == "" or value is None:
271+
return queryset # No filtering
272+
273+
has_data = value in [True, "True", "true", "1"]
274+
275+
if has_data:
276+
# Has data: exclude null and empty dict
277+
return queryset.exclude(Q(type_specific_data__isnull=True) | Q(type_specific_data={}))
271278
else:
272-
# Fallback: show all segments
273-
return queryset
279+
# No data: include null or empty dict
280+
return queryset.filter(Q(type_specific_data__isnull=True) | Q(type_specific_data={}))
274281

275282
def _parse_smart_numeric_value(self, value, field_type="float"):
276283
"""

cesnet_service_path_plugin/forms/segment.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,16 +454,28 @@ class SegmentFilterForm(NetBoxModelFilterSetForm):
454454
label=_("Circuits"),
455455
)
456456

457-
has_path_data = forms.MultipleChoiceField(
457+
has_path_data = forms.ChoiceField(
458458
required=False,
459459
choices=[
460+
("", "Any"),
460461
(True, "Yes"),
461462
(False, "No"),
462463
],
463464
label=_("Has Path Data"),
464465
help_text="Filter segments that have path geometry data",
465466
)
466467

468+
has_type_specific_data = forms.ChoiceField(
469+
required=False,
470+
choices=[
471+
("", "Any"),
472+
(True, "Yes"),
473+
(False, "No"),
474+
],
475+
label=_("Has Type-Specific Data"),
476+
help_text="Filter segments that have type-specific data defined",
477+
)
478+
467479
# =============================================================================
468480
# TYPE-SPECIFIC FILTER FIELDS - SIMPLIFIED (NO SmartNumericField needed)
469481
# =============================================================================
@@ -620,7 +632,9 @@ class SegmentFilterForm(NetBoxModelFilterSetForm):
620632

621633
fieldsets = (
622634
FieldSet("q", "tag", "filter_id", name="General"),
623-
FieldSet("name", "status", "segment_type", "network_label", "has_path_data", name="Basic"),
635+
FieldSet(
636+
"name", "status", "segment_type", "network_label", "has_path_data", "has_type_specific_data", name="Basic"
637+
),
624638
FieldSet(
625639
"provider_id",
626640
"provider_segment_id",

cesnet_service_path_plugin/graphql/filters.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ class SegmentFilter(NetBoxModelFilterMixin):
7878
@strawberry_django.filter_field
7979
def has_path_data(self, value: bool, prefix: str) -> Q:
8080
"""Filter segments based on whether they have path geometry data"""
81-
logging.debug(f"Filtering segments with has_path_data={value}")
8281
if value:
8382
# Filter for segments WITH path data
8483
return Q(**{f"{prefix}path_geometry__isnull": False})

0 commit comments

Comments
 (0)