Extending Filters¶
Added in version 1.3.0
Apps can extend any model-based FilterSet and FilterForm classes that are provided by the Nautobot core.
The requirements to extend a filter set or a filter form (or both) are:
- The file must be named
filter_extensions.py - The variable
filter_extensionsmust be declared in that file, and contain a list ofFilterExtensionsubclasses - The
modelattribute of eachFilterExtensionsubclass must be set to a valid model name in the dotted pair format ({app_label}.{model}, e.g.tenant.tenantordcim.device)
Nautobot dynamically creates many additional filters based upon the defined filter type. Specifically, there are additional lookup expressions (referred to in code as lookup_expr) that are created for each filter, when there is neither a lookup_expr nor method parameter already set. These dynamically-added lookup expressions are added using a shorthand notation (e.g. icontains is ic). Nautobot will also add the negation of each, for example, so icontains will be added along with not icontains using the ic and nic expressions respectively.
The dynamically-added lookup expressions can be found in the source code at nautobot/core/constants.py and the mapping logic can be found in nautobot/core/filters.py. Please see the documentation on filtering for more information.
Tip
For developers of apps that define their own model filters, note that the above are added dynamically, as long as the class inherits from nautobot.apps.filters.BaseFilterSet.
However, that does not cover every possible use case, to list a few examples:
- Usage of a custom
methodargument on a filter that points to aFilterSetmethod, which would allow arbitrary filtering using custom logic. This is how theqfield search logic is currently performed. - Creation of a filter on a field that does not currently have filtering support
- Convenience methods for highly nested fields
There are several conditions that must be met in order to extend a filter:
- The original FilterSet must follow the pattern:
f"{model.__name__}FilterSet"e.g.TenantFilterSet - The
FilterExtension.filterset_fieldsattribute must be a valid dict, with each key being the filter name (which must start with the plugin'sname+_, e.g."example_plugin_description", not merely"description") and each value being a valid django-filter filter
Nautobot will dynamically generate the additional relevant lookup expressions of an app's defined custom FilterSet field, so no need to additionally register example_plugin_description__ic, etc.
Similar to FilterSet fields, Nautobot provides a default filter form for each model, however that does not cover every possible use case. To list a few examples of why one may want to extend a filter form:
- The base filter form does not include a custom filter defined by the app as described above
- The base filter form does not provide a specific lookup expression to a filterable field, such as allowing regex on name
There are several conditions that must be met in order to extend a filter:
- The original
FilterFormmust follow the pattern:f"{model.__name__}FilterForm", e.g.TenantFilterForm - The
filterform_fieldsattribute must be a valid dictionary of Django form fields
Note
An app is not required to define both filterset_fields and filterform_fields.
You can view an example of filter_extensions.py by viewing the one provided with the Example Plugin.
Tip
The method parameter, if used, must be a callable (method/function). Note that because filters with a method do their filtering in Python code rather than at the database level, performance of method filters is generally much poorer than pure-database filters. The method parameter is not supported when using Dynamic Groups.