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_extensions
must be declared in that file, and contain a list ofFilterExtension
subclasses - The
model
attribute of eachFilterExtension
subclass must be set to a valid model name in the dotted pair format ({app_label}.{model}
, e.g.tenant.tenant
ordcim.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
method
argument on a filter that points to aFilterSet
method, which would allow arbitrary filtering using custom logic. This is how theq
field 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_fields
attribute must be a valid dict, with each key being the filter name (which must start with the App'sname
+_
, e.g."example_app_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_app_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
FilterForm
must follow the pattern:f"{model.__name__}FilterForm"
, e.g.TenantFilterForm
- The
filterform_fields
attribute 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 App.
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.