diff --git a/netbox/circuits/graphql/filters.py b/netbox/circuits/graphql/filters.py index 2d6e75d14..ce478f0aa 100644 --- a/netbox/circuits/graphql/filters.py +++ b/netbox/circuits/graphql/filters.py @@ -1,11 +1,14 @@ from typing import List +import django_filters import strawberry import strawberry_django from circuits import filtersets, models +from functools import partial, partialmethod, wraps from strawberry import auto from strawberry_django.filters import FilterLookup from tenancy.graphql.filter_mixins import ContactModelFilterMixin, TenancyFilterMixin +from utilities.filters import * from netbox.graphql.filter_mixins import NetBoxModelFilterMixin @@ -18,6 +21,167 @@ __all__ = ( 'ProviderNetworkFilter', ) +# def filter_by_filterset(self, queryset, key, cls, filterset): +# breakpoint() +# return filterset(data={key: getattr(cls, key)}, queryset=queryset).qs + + +def autotype_decorator(filterset): + + def wrapper(cls): + cls.filterset = filterset + fields = filterset.get_fields() + print(f"fields: {fields}") + for fieldname in fields.keys(): + if fieldname not in cls.__annotations__: + cls.__annotations__[fieldname] = auto + + # fields = list(filterset.get_fields().keys()) + declared_filters = filterset.declared_filters + print(f"declared_filters: {declared_filters}") + print("") + for fieldname, v in declared_filters.items(): + create_function = False + attr_type = None + print(f"{fieldname}: {v}") + + if isinstance(v, ContentTypeFilter): + print("ContentTypeFilter") + elif isinstance(v, MACAddressFilter): + print("MACAddressFilter") + elif isinstance(v, MultiValueArrayFilter): + print("MultiValueArrayFilter") + elif isinstance(v, MultiValueCharFilter): + print("MultiValueCharFilter") + elif isinstance(v, MultiValueDateFilter): + print("MultiValueDateFilter") + elif isinstance(v, MultiValueDateTimeFilter): + print("MultiValueDateTimeFilter") + elif isinstance(v, MultiValueDecimalFilter): + print("MultiValueDecimalFilter") + elif isinstance(v, MultiValueMACAddressFilter): + print("MultiValueMACAddressFilter") + elif isinstance(v, MultiValueNumberFilter): + print("MultiValueNumberFilter") + elif isinstance(v, MultiValueTimeFilter): + print("MultiValueTimeFilter") + elif isinstance(v, MultiValueWWNFilter): + print("MultiValueWWNFilter") + elif isinstance(v, NullableCharFieldFilter): + print("NullableCharFieldFilter") + elif isinstance(v, NumericArrayFilter): + print("NumericArrayFilter") + elif isinstance(v, TreeNodeMultipleChoiceFilter): + print("TreeNodeMultipleChoiceFilter") + + elif issubclass(type(v), django_filters.CharFilter): + print("CharFilter") + elif issubclass(type(v), django_filters.UUIDFilter): + print("UUIDFilter") + elif issubclass(type(v), django_filters.BooleanFilter): + print("BooleanFilter") + elif issubclass(type(v), django_filters.ChoiceFilter): + print("ChoiceFilter") + elif issubclass(type(v), django_filters.TypedChoiceFilter): + print("TypedChoiceFilter") + elif issubclass(type(v), django_filters.DateFilter): + print("DateFilter") + elif issubclass(type(v), django_filters.TimeFilter): + print("TimeFilter") + elif issubclass(type(v), django_filters.DateTimeFilter): + print("DateTimeFilter") + elif issubclass(type(v), django_filters.IsoDateTimeFilter): + print("IsoDateTimeFilter") + elif issubclass(type(v), django_filters.DurationFilter): + print("DurationFilter") + elif issubclass(type(v), django_filters.ModelChoiceFilter): + print("ModelChoiceFilter") + elif issubclass(type(v), django_filters.ModelMultipleChoiceFilter): + create_function = True + attr_type = List[str] | None + print("ModelMultipleChoiceFilter") + elif issubclass(type(v), django_filters.NumberFilter): + print("NumberFilter") + elif issubclass(type(v), django_filters.NumericRangeFilter): + print("NumericRangeFilter") + elif issubclass(type(v), django_filters.RangeFilter): + print("RangeFilter") + elif issubclass(type(v), django_filters.DateRangeFilter): + print("DateRangeFilter") + elif issubclass(type(v), django_filters.DateFromToRangeFilter): + print("DateFromToRangeFilter") + elif issubclass(type(v), django_filters.DateTimeFromToRangeFilter): + print("DateTimeFromToRangeFilter") + elif issubclass(type(v), django_filters.IsoDateTimeFromToRangeFilter): + print("IsoDateTimeFromToRangeFilter") + elif issubclass(type(v), django_filters.TimeRangeFilter): + print("TimeRangeFilter") + elif issubclass(type(v), django_filters.AllValuesFilter): + print("AllValuesFilter") + elif issubclass(type(v), django_filters.AllValuesMultipleFilter): + print("AllValuesMultipleFilter") + elif issubclass(type(v), django_filters.LookupChoiceFilter): + print("LookupChoiceFilter") + elif issubclass(type(v), django_filters.BaseInFilter): + print("BaseInFilter") + elif issubclass(type(v), django_filters.BaseRangeFilter): + print("BaseRangeFilter") + elif issubclass(type(v), django_filters.OrderingFilter): + print("OrderingFilter") + elif issubclass(type(v), django_filters.TypedMultipleChoiceFilter): + print("TypedMultipleChoiceFilter") + elif issubclass(type(v), django_filters.MultipleChoiceFilter): + print("MultipleChoiceFilter") + else: + print("unknown type!") + + if fieldname not in cls.__annotations__ and attr_type: + print(f"adding {fieldname} to class") + cls.__annotations__[fieldname] = attr_type + + fname = f"filter_{fieldname}" + if create_function and not hasattr(cls, fname): + print(f"creating function {fname}") + filter_by_filterset = getattr(cls, 'filter_by_filterset') + setattr(cls, fname, partialmethod(filter_by_filterset, key=fieldname)) + # setattr(cls, fname, partial(filter_by_filterset, key=fieldname, cls=cls, filterset=filterset)) + + print("") + return cls + + return wrapper + + +""" +class autotype_decorator(object): + def __init__(self, filterset): + self.filterset = filterset + def __call__(self, cls): + class Wrapped(cls): + ''' + cls.filterset = filterset + fields = filterset.get_fields() + print(fields) + fields = list(filterset.get_fields().keys()) + declared_filters = filterset.declared_filters + print(declared_filters) + fields.extend(list(filterset.declared_filters.keys())) + for field in fields: + print(field) + + ''' + print(f"cls: {cls}") + print(f"self: {self}") + vars()['cid'] = strawberry.unset.UnsetType + # setattr(cls, 'cid', strawberry.unset.UnsetType) + pass + + setattr(Wrapped, 'cid', strawberry.unset.UnsetType) + print(f"hasattr: {hasattr(Wrapped, 'cid')}") + print(Wrapped) + return Wrapped +""" + @strawberry_django.filter(models.CircuitTermination, lookups=True) class CircuitTerminationFilter(filtersets.CircuitTerminationFilterSet): @@ -36,10 +200,17 @@ class CircuitTerminationFilter(filtersets.CircuitTerminationFilterSet): @strawberry_django.filter(models.Circuit, lookups=True) -class CircuitFilter(NetBoxModelFilterMixin, TenancyFilterMixin, ContactModelFilterMixin): - filterset = filtersets.CircuitFilterSet +@autotype_decorator(filtersets.CircuitFilterSet) +class CircuitFilter: + # class CircuitFilter(NetBoxModelFilterMixin, TenancyFilterMixin, ContactModelFilterMixin): - cid: auto + def filter_by_filterset(self, queryset, key): + return self.filterset(data={key: getattr(self, key)}, queryset=queryset).qs + + pass + """ + # vars()['cid'] = strawberry.unset.UnsetType + # cid: auto description: auto install_date: auto termination_date: auto @@ -94,6 +265,7 @@ class CircuitFilter(NetBoxModelFilterMixin, TenancyFilterMixin, ContactModelFilt def filter_site(self, queryset): return self.filter_by_filterset(queryset, 'site') + """ # @strawberry_django.filter(models.Circuit, lookups=True)