Allow plugins to extend autotype decorator function #9657

Closed
opened 2025-12-29 21:20:29 +01:00 by adam · 5 comments
Owner

Originally created by @amyasnikov on GitHub (May 11, 2024).

NetBox version

v4.0.1

Feature type

Change to existing functionality

Proposed functionality

Problem
NetBox 4.0 Plugin migration guide suggests using autotype_decorator to convert filtersets into strawberry filters. However, this decorator does not support a lot of existing filters (e.g. ChoiceFilter):

import django_filters
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
from dcim import models, choices
import strawberry_django

class MyFilterSet(django_filters.FilterSet):
     type = django_filters.ChoiceFilter(choices=choices.ConsolePortTypeChoices)
     class Meta:
         model = models.ConsolePort
         fields = ['type']

@strawberry_django.filter(models.ConsolePort, lookups=True)
@autotype_decorator(MyFilterSet)
class MyFilter(BaseFilterMixin):
    pass

# NotImplementedError: GraphQL Filter field unknown: type: <django_filters.filters.ChoiceFilter object at 0x7fa9d06bb370>

This error also ruins all the work made by autotype_decorator for any other filters inside FilterSet. Hence, it would be very painful to handle it at the plugin side.

Possible Solution
Just use Dependency Injection to inject map_strawberry_type inside autotype_decorator:

def autotype_decorator(filterset, map_strawberry_type_fn=map_strawberry_type):
   ...
   should_create_function, attr_type = map_strawberry_type_fn(field)
   ...

This would allow plugin developers to supply their own map_strawberry_type_fn for their own filters when using autotype_decorator.

Use case

Plugin developers will be allowed to handle arbitrary filter types by themselves:

def map_strawberry_extra(field):
    create_fn, attr_type = map_strawberry_type(field)
    if attr_type is None and isinstance(field, ChoiceFilter):
        return True, str | None
    return create_fn, attr_type

@strawberry_django.filter(models.ConsolePort, lookups=True)
@autotype_decorator(MyFilterSet, map_strawberry_type_fn=map_strawberry_extra)
class MyFilter(BaseFilterMixin):
    pass

# No error

I can make a PR if you're okay with this change

Database changes

No response

External dependencies

No response

Originally created by @amyasnikov on GitHub (May 11, 2024). ### NetBox version v4.0.1 ### Feature type Change to existing functionality ### Proposed functionality **Problem** NetBox 4.0 Plugin migration guide suggests using [autotype_decorator](https://github.com/netbox-community/netbox/blob/4a64a3f6e0d0edf27996422eb2dbe0e197a6bea5/netbox/netbox/graphql/filter_mixins.py#L130) to convert filtersets into strawberry filters. However, this decorator does not support a lot of existing filters (e.g. `ChoiceFilter`): ```python import django_filters from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin from dcim import models, choices import strawberry_django class MyFilterSet(django_filters.FilterSet): type = django_filters.ChoiceFilter(choices=choices.ConsolePortTypeChoices) class Meta: model = models.ConsolePort fields = ['type'] @strawberry_django.filter(models.ConsolePort, lookups=True) @autotype_decorator(MyFilterSet) class MyFilter(BaseFilterMixin): pass # NotImplementedError: GraphQL Filter field unknown: type: <django_filters.filters.ChoiceFilter object at 0x7fa9d06bb370> ``` This error also ruins all the work made by `autotype_decorator` for any other filters inside FilterSet. Hence, it would be very painful to handle it at the plugin side. **Possible Solution** Just use **Dependency Injection** to inject `map_strawberry_type` inside `autotype_decorator`: ```python def autotype_decorator(filterset, map_strawberry_type_fn=map_strawberry_type): ... should_create_function, attr_type = map_strawberry_type_fn(field) ... ``` This would allow plugin developers to supply their own `map_strawberry_type_fn` for their own filters when using `autotype_decorator`. ### Use case Plugin developers will be allowed to handle arbitrary filter types by themselves: ```python def map_strawberry_extra(field): create_fn, attr_type = map_strawberry_type(field) if attr_type is None and isinstance(field, ChoiceFilter): return True, str | None return create_fn, attr_type @strawberry_django.filter(models.ConsolePort, lookups=True) @autotype_decorator(MyFilterSet, map_strawberry_type_fn=map_strawberry_extra) class MyFilter(BaseFilterMixin): pass # No error ``` I can make a PR if you're okay with this change ### Database changes _No response_ ### External dependencies _No response_
adam added the type: featurecomplexity: mediumnetbox labels 2025-12-29 21:20:29 +01:00
adam closed this issue 2025-12-29 21:20:29 +01:00
Author
Owner

@jeffgdotorg commented on GitHub (May 13, 2024):

Thank you for your interest in helping improve NetBox. Making life easier for plugin developers is important to us too.

My role at this stage is just to triage; others on the team with deeper understanding of the factors in play will need to take a closer look to determine whether your proposal is viable with fully gamed out. I'm setting the issue's status to under review and will raise it with the team.

Thanks for volunteering to work it through to a PR, but we ask that you please wait until you see the status move to accepted and the issue assigned to you before doing so.

@jeffgdotorg commented on GitHub (May 13, 2024): Thank you for your interest in helping improve NetBox. Making life easier for plugin developers is important to us too. My role at this stage is just to triage; others on the team with deeper understanding of the factors in play will need to take a closer look to determine whether your proposal is viable with fully gamed out. I'm setting the issue's status to `under review` and will raise it with the team. Thanks for volunteering to work it through to a PR, but we ask that you *please wait* until you see the status move to `accepted` and the issue assigned to you before doing so.
Author
Owner

@amyasnikov commented on GitHub (May 19, 2024):

@jeffgdotorg Hi, any news on this issue?

@amyasnikov commented on GitHub (May 19, 2024): @jeffgdotorg Hi, any news on this issue?
Author
Owner

@derdeagle commented on GitHub (Nov 9, 2024):

I just stumbled upon the the same problem while trying to extend an existing plugin. If the type of the property is ChoiceFilter it does not work while it does if the type is MultipleChoiceFilter.

I am currently using version 4.1.6 in the official docker container (extended as described in the official documentation).

The error message is:

[netbox-housekeeping] | Traceback (most recent call last):
[netbox-housekeeping] |   File "/opt/netbox/netbox/manage.py", line 10, in <module>
[netbox-housekeeping] |     execute_from_command_line(sys.argv)
[netbox-housekeeping] |   File "/opt/netbox/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
[netbox-housekeeping] |     utility.execute()
[netbox-housekeeping] |   File "/opt/netbox/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 416, in execute
[netbox-housekeeping] |     django.setup()
[netbox-housekeeping] |   File "/opt/netbox/venv/lib/python3.12/site-packages/django/__init__.py", line 24, in setup
[netbox-housekeeping] |     apps.populate(settings.INSTALLED_APPS)
[netbox-housekeeping] |   File "/opt/netbox/venv/lib/python3.12/site-packages/django/apps/registry.py", line 124, in populate
[netbox-housekeeping] |     app_config.ready()
[netbox-housekeeping] |   File "/opt/netbox/venv/lib/python3.12/site-packages/netbox_data_flows/__init__.py", line 24, in ready
[netbox-housekeeping] |     super().ready()
[netbox-housekeeping] |   File "/opt/netbox/netbox/netbox/plugins/__init__.py", line 125, in ready
[netbox-housekeeping] |     if graphql_schema := self._load_resource('graphql_schema'):
[netbox-housekeeping] |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[netbox-housekeeping] |   File "/opt/netbox/netbox/netbox/plugins/__init__.py", line 91, in _load_resource
[netbox-housekeeping] |     module = import_module(default_module)
[netbox-housekeeping] |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[netbox-housekeeping] |   File "/usr/lib/python3.12/importlib/__init__.py", line 90, in import_module
[netbox-housekeeping] |     return _bootstrap._gcd_import(name[level:], package, level)
[netbox-housekeeping] |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[netbox-housekeeping] |   File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
[netbox-housekeeping] |   File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
[netbox-housekeeping] |   File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
[netbox-housekeeping] |   File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
[netbox-housekeeping] |   File "<frozen importlib._bootstrap_external>", line 995, in exec_module
[netbox-housekeeping] |   File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
[netbox-housekeeping] |   File "/opt/netbox/venv/lib/python3.12/site-packages/netbox_data_flows/graphql.py", line 16, in <module>
[netbox-housekeeping] |     @autotype_decorator(filtersets.DataFlowFilterSet)
[netbox-housekeeping] |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[netbox-housekeeping] |   File "/opt/netbox/netbox/netbox/graphql/filter_mixins.py", line 191, in wrapper
[netbox-housekeeping] |     raise NotImplementedError(f"GraphQL Filter field unknown: {fieldname}: {field}")
[netbox-housekeeping] | NotImplementedError: GraphQL Filter field unknown: status: <django_filters.filters.ChoiceFilter object at 0x7282baaf5c10>

Is there already an update on this?

@derdeagle commented on GitHub (Nov 9, 2024): I just stumbled upon the the same problem while trying to extend an existing plugin. If the type of the property is `ChoiceFilter` it does not work while it does if the type is `MultipleChoiceFilter`. I am currently using version 4.1.6 in the official docker container (extended as described in the official documentation). The error message is: ``` [netbox-housekeeping] | Traceback (most recent call last): [netbox-housekeeping] | File "/opt/netbox/netbox/manage.py", line 10, in <module> [netbox-housekeeping] | execute_from_command_line(sys.argv) [netbox-housekeeping] | File "/opt/netbox/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line [netbox-housekeeping] | utility.execute() [netbox-housekeeping] | File "/opt/netbox/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 416, in execute [netbox-housekeeping] | django.setup() [netbox-housekeeping] | File "/opt/netbox/venv/lib/python3.12/site-packages/django/__init__.py", line 24, in setup [netbox-housekeeping] | apps.populate(settings.INSTALLED_APPS) [netbox-housekeeping] | File "/opt/netbox/venv/lib/python3.12/site-packages/django/apps/registry.py", line 124, in populate [netbox-housekeeping] | app_config.ready() [netbox-housekeeping] | File "/opt/netbox/venv/lib/python3.12/site-packages/netbox_data_flows/__init__.py", line 24, in ready [netbox-housekeeping] | super().ready() [netbox-housekeeping] | File "/opt/netbox/netbox/netbox/plugins/__init__.py", line 125, in ready [netbox-housekeeping] | if graphql_schema := self._load_resource('graphql_schema'): [netbox-housekeeping] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [netbox-housekeeping] | File "/opt/netbox/netbox/netbox/plugins/__init__.py", line 91, in _load_resource [netbox-housekeeping] | module = import_module(default_module) [netbox-housekeeping] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [netbox-housekeeping] | File "/usr/lib/python3.12/importlib/__init__.py", line 90, in import_module [netbox-housekeeping] | return _bootstrap._gcd_import(name[level:], package, level) [netbox-housekeeping] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [netbox-housekeeping] | File "<frozen importlib._bootstrap>", line 1387, in _gcd_import [netbox-housekeeping] | File "<frozen importlib._bootstrap>", line 1360, in _find_and_load [netbox-housekeeping] | File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked [netbox-housekeeping] | File "<frozen importlib._bootstrap>", line 935, in _load_unlocked [netbox-housekeeping] | File "<frozen importlib._bootstrap_external>", line 995, in exec_module [netbox-housekeeping] | File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed [netbox-housekeeping] | File "/opt/netbox/venv/lib/python3.12/site-packages/netbox_data_flows/graphql.py", line 16, in <module> [netbox-housekeeping] | @autotype_decorator(filtersets.DataFlowFilterSet) [netbox-housekeeping] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [netbox-housekeeping] | File "/opt/netbox/netbox/netbox/graphql/filter_mixins.py", line 191, in wrapper [netbox-housekeeping] | raise NotImplementedError(f"GraphQL Filter field unknown: {fieldname}: {field}") [netbox-housekeeping] | NotImplementedError: GraphQL Filter field unknown: status: <django_filters.filters.ChoiceFilter object at 0x7282baaf5c10> ``` Is there already an update on this?
Author
Owner

@github-actions[bot] commented on GitHub (Apr 25, 2025):

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. Do not attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our contributing guide.

@github-actions[bot] commented on GitHub (Apr 25, 2025): This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. **Do not** attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our [contributing guide](https://github.com/netbox-community/netbox/blob/main/CONTRIBUTING.md).
Author
Owner

@jeremystretch commented on GitHub (Apr 25, 2025):

Beginning with NetBox v4.3 the GraphQL API no longer reuses the REST/UI filtersets; plugins will need to provide their own filtersets, so this constraint no longer applies.

@jeremystretch commented on GitHub (Apr 25, 2025): Beginning with NetBox v4.3 the GraphQL API no longer reuses the REST/UI filtersets; plugins will need to provide their own filtersets, so this constraint no longer applies.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#9657