Skip to content

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 of FilterExtension subclasses
  • The model attribute of each FilterExtension subclass must be set to a valid model name in the dotted pair format ({app_label}.{model}, e.g. tenant.tenant or dcim.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 a FilterSet method, which would allow arbitrary filtering using custom logic. This is how the q 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's name + _, 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.