Skip to content

nautobot.apps.utils

Nautobot utility functions.

nautobot.apps.utils.ChangeLoggedModelsQuery

Bases: FeaturedQueryMixin

Helper class to get ContentType for models that implements the to_objectchange method for change logging.

list_subclasses()

Return a list of classes that implement the to_objectchange method

nautobot.apps.utils.FeatureQuery

Helper class that delays evaluation of the registry contents for the functionality store until it has been populated.

as_dict()

Given an extras feature, return a dict of app_label: [models] for content type lookup

get_choices()

Given an extras feature, return a list of 2-tuple of (model_label, pk) suitable for use as choices on a choice field:

>>> FeatureQuery('statuses').get_choices()
[('dcim.device', 13), ('dcim.rack', 34)]

get_query()

Given an extras feature, return a Q object for content type lookup

list_subclasses()

Return a list of model classes that declare this feature.

nautobot.apps.utils.FeaturedQueryMixin

Mixin class that gets a list of featured models.

__call__()

Given an extras feature, return a Q object for content type lookup

list_subclasses()

Return a list of classes that has implements this name.

nautobot.apps.utils.GitRepo

head property

Current checked out repository head commit.

__init__(path, url, clone_initially=True)

Ensure that we have a clone of the given remote Git repository URL at the given local directory path.

Parameters:

Name Type Description Default
path str

path to git repo

required
url str

git repo url

required
clone_initially bool

True if the repo needs to be cloned

True

checkout(branch, commit_hexsha=None)

Check out the given branch, and optionally the specified commit within that branch.

Returns:

Type Description
(str, bool)

commit_hexsha the repo contains now, whether any change occurred

nautobot.apps.utils.RoleModelsQuery

Bases: FeaturedQueryMixin

Helper class to get ContentType models that implements role.

list_subclasses()

Return a list of classes that implements roles e.g roles = ...

nautobot.apps.utils.TaggableClassesQuery

Bases: FeaturedQueryMixin

Helper class to get ContentType models that implements tags(TagsField)

list_subclasses()

Return a list of classes that has implements tags e.g tags = TagsField(...)

nautobot.apps.utils.build_lookup_label(field_name, _verbose_name)

Return lookup expr with its verbose name

Parameters:

Name Type Description Default
field_name str

Field name e.g name__iew

required
_verbose_name str

The verbose name for the lookup expr which is suffixed to the field name e.g iew -> iendswith

required

Examples:

>>> build_lookup_label("name__iew", "iendswith")
>>> "ends-with (iew)"

nautobot.apps.utils.check_if_key_is_graphql_safe(model_name, key, field_name='key')

Helper method to check if a key field is Python/GraphQL safe. Used in CustomField, ComputedField and Relationship models.

nautobot.apps.utils.class_deprecated(message)

Decorator to mark a class as deprecated with a custom message about what to do instead of subclassing it.

nautobot.apps.utils.class_deprecated_in_favor_of(replacement_class)

Decorator to mark a class as deprecated and suggest a replacement class if it is subclassed from.

nautobot.apps.utils.convert_git_diff_log_to_list(logs)

Convert Git diff log into a list splitted by \n

Example:
    >>> git_log = "M        index.html

R sample.txt" >>> print(convert_git_diff_log_to_list(git_log)) ["Modification - index.html", "Renaming - sample.txt"]

nautobot.apps.utils.convert_querydict_to_factory_formset_acceptable_querydict(request_querydict, filterset)

Convert request QueryDict/GET into an acceptable factory formset QueryDict while discarding querydict params which are not part of filterset_class params

Parameters:

Name Type Description Default
request_querydict QueryDict

QueryDict to convert

required
filterset FilterSet

Filterset class

required

Examples:

>>> convert_querydict_to_factory_formset_acceptable_querydict({"status": ["active", "decommissioning"], "name__ic": ["location"]},)
>>> {
...     'form-TOTAL_FORMS': [3],
...     'form-INITIAL_FORMS': ['0'],
...     'form-MIN_NUM_FORMS': [''],
...     'form-MAX_NUM_FORMS': [''],
...     'form-0-lookup_field': ['status'],
...     'form-0-lookup_type': ['status'],
...     'form-0-value': ['active', 'decommissioning'],
...     'form-1-lookup_field': ['name'],
...     'form-1-lookup_type': ['name__ic'],
...     'form-1-value': ['location']
... }

nautobot.apps.utils.custom_validator_clean(model_clean_func)

Decorator that wraps a models existing clean method to also execute registered plugin custom validators

:param model_clean_func: The original model clean method which is to be wrapped

nautobot.apps.utils.deepmerge(original, new)

Deep merge two dictionaries (new into original) and return a new dict

nautobot.apps.utils.ensure_content_type_and_field_name_in_query_params(query_params)

Ensure query_params includes content_type and field_name and content_type is a valid ContentType.

Return the 'ContentTypes' model and 'field_name' if validation was successful.

nautobot.apps.utils.fixup_null_statuses(*, model, model_contenttype, status_model)

For instances of model that have an invalid NULL status field, create and use a special status_model instance.

nautobot.apps.utils.flatten_dict(d, prefix='', separator='.')

Flatten nested dictionaries into a single level by joining key names with a separator.

:param d: The dictionary to be flattened :param prefix: Initial prefix (if any) :param separator: The character to use when concatenating key names

nautobot.apps.utils.flatten_iterable(iterable)

Flatten a nested iterable such as a list of lists, keeping strings intact.

:param iterable: The iterable to be flattened :returns: generator

nautobot.apps.utils.foreground_color(bg_color)

Return the ideal foreground color (black or white) for a given background color in hexadecimal RGB format.

nautobot.apps.utils.generate_signature(request_body, secret)

Return a cryptographic signature that can be used to verify the authenticity of webhook data.

nautobot.apps.utils.get_all_lookup_expr_for_field(model, field_name)

Return all lookup expressions for field_name in model filterset

nautobot.apps.utils.get_all_new_ui_ready_routes()

nautobot.apps.utils.get_base_template(base_template, model)

Returns the name of the base template, if the base_template is not None Otherwise, default to using "/.html" as the base template, if it exists. Otherwise, check if "/_retrieve.html" used in NautobotUIViewSet exists. If both templates do not exist, fall back to "base.html".

nautobot.apps.utils.get_celery_queues()

Return a dictionary of celery queues and the number of workers active on the queue in the form {queue_name: num_workers}

nautobot.apps.utils.get_changes_for_model(model)

Return a queryset of ObjectChanges for a model or instance. The queryset will be filtered by the model class. If an instance is provided, the queryset will also be filtered by the instance id.

nautobot.apps.utils.get_filter_field_label(filter_field)

Return a label for a given field name and value.

Parameters:

Name Type Description Default
filter_field Filter

The filter to get a label for

required

Returns:

Type Description
str

The label for the given field

nautobot.apps.utils.get_filterable_params_from_filter_params(filter_params, non_filter_params, filterset)

Remove any non_filter_params and fields that are not a part of the filterset from filter_params to return only queryset filterable parameters.

Parameters:

Name Type Description Default
filter_params QueryDict

Filter param querydict

required
non_filter_params list

Non queryset filterable params

required
filterset FilterSet

The FilterSet class

required

Returns:

Type Description
QueryDict

Filter param querydict with only queryset filterable params

nautobot.apps.utils.get_filterset_for_model(model)

Return the FilterSet class associated with a given model.

The FilterSet class is expected to be in the filters module within the application associated with the model and its name is expected to be {ModelName}FilterSet.

If a matching FilterSet is not found, this will return None.

Parameters:

Name Type Description Default
model BaseModel

A model class

required

Returns:

Type Description
Union[FilterSet, None]

Either the FilterSet class or None

nautobot.apps.utils.get_filterset_parameter_form_field(model, parameter, filterset=None)

Return the relevant form field instance for a filterset parameter e.g DynamicModelMultipleChoiceField, forms.IntegerField e.t.c

nautobot.apps.utils.get_form_for_model(model, form_prefix='')

Return the Form class associated with a given model.

The Form class is expected to be in the forms module within the application associated with the model and its name is expected to be {ModelName}{form_prefix}Form.

If a matching Form is not found, this will return None.

Parameters:

Name Type Description Default
form_prefix str

An additional prefix for the form name (e.g. Filter, such as to retrieve FooFilterForm) that will come after the model name.

''

Returns:

Type Description
Union[Form, None]

Either the Form class or None

nautobot.apps.utils.get_latest_release(pre_releases=False)

Get latest known Nautobot release from cache, or if not available, queue up a background task to populate the cache.

Returns:

Type Description
(Version, str)

Latest release version and the release URL, if found in the cache

(unknown, None)

If not present in the cache at this time

nautobot.apps.utils.get_model_from_name(model_name)

Given a full model name in dotted format (example: dcim.model), a model class is returned if valid.

:param model_name: Full dotted name for a model as a string (ex: dcim.model) :type model_name: str

:raises TypeError: If given model name is not found.

:return: Found model.

nautobot.apps.utils.get_only_new_ui_ready_routes(patterns, prefix='')

Recursively traverses Django URL patterns to find routes associated with view classes that have the use_new_ui attribute set to True.

Parameters:

Name Type Description Default
patterns list

List of URL patterns to traverse.

required
prefix str

URL pattern prefix to include when constructing route patterns.

''

Returns:

Type Description
list

A list of route patterns associated with view classes that use the new UI.

nautobot.apps.utils.get_permission_for_model(model, action)

Resolve the named permission for a given model (or instance) and action (e.g. view or add).

:param model: A model or instance :param action: View, add, change, or delete (string)

Return the appropriate class associated with a given model matching the module_name and object_suffix.

The given model can either be a model class, a model instance, or a dotted representation (ex: dcim.device).

The object class is expected to be in the module within the application associated with the model and its name is expected to be {ModelName}{object_suffix}.

If a matching class is not found, this will return None.

Parameters:

Name Type Description Default
model Union[BaseModel, str]

A model class, instance, or dotted representation

required
module_name str

The name of the module to search for the object class

required
object_suffix str

The suffix to append to the model name to find the object class

required

Returns:

Type Description
Union[BaseModel, str]

Either the matching object class or None

nautobot.apps.utils.get_route_for_model(model, action, api=False)

Return the URL route name for the given model and action. Does not perform any validation. Supports both core and App routes.

Parameters:

Name Type Description Default
model (Model, str)

Class, Instance, or dotted string of a Django Model

required
action str

name of the action in the route

required
api bool

If set, return an API route.

False

Returns:

Type Description
str

return the name of the view for the model/action provided.

Examples:

>>> get_route_for_model(Device, "list")
"dcim:device_list"
>>> get_route_for_model(Device, "list", api=True)
"dcim-api:device-list"
>>> get_route_for_model("dcim.location", "list")
"dcim:location_list"
>>> get_route_for_model("dcim.location", "list", api=True)
"dcim-api:location-list"
>>> get_route_for_model(ExampleModel, "list")
"plugins:example_app:examplemodel_list"
>>> get_route_for_model(ExampleModel, "list", api=True)
"plugins-api:example_app-api:examplemodel-list"

nautobot.apps.utils.get_settings_or_config(variable_name)

Get a value from Django settings (if specified there) or Constance configuration (otherwise).

nautobot.apps.utils.get_table_for_model(model)

Return the Table class associated with a given model.

The Table class is expected to be in the tables module within the application associated with the model and its name is expected to be {ModelName}Table.

If a matching Table is not found, this will return None.

Parameters:

Name Type Description Default
model BaseModel

A model class

required

Returns:

Type Description
Union[Table, None]

Either the Table class or None

nautobot.apps.utils.get_url_for_url_pattern(url_pattern)

Given a URL pattern, construct a URL string that would match that pattern.

Examples:

>>> get_url_for_url_pattern("/plugins/example-app/^models/(?P<pk>[^/.]+)/$")
'/plugins/example-app/models/00000000-0000-0000-0000-000000000000/'
>>> get_url_for_url_pattern("/circuits/circuit-terminations/<uuid:termination_a_id>/connect/<str:termination_b_type>/")
'/circuits/circuit-terminations/00000000-0000-0000-0000-000000000000/connect/string/'

nautobot.apps.utils.get_url_patterns(urlconf=None, patterns_list=None, base_path='/')

Recursively yield a list of registered URL patterns.

Parameters:

Name Type Description Default
urlconf URLConf

Python module such as nautobot.core.urls. Default if unspecified is the value of settings.ROOT_URLCONF, i.e. the nautobot.core.urls module.

None
patterns_list list

Used in recursion. Generally can be omitted on initial call. Default if unspecified is the url_patterns attribute of the given urlconf module.

None
base_path str

String to prepend to all URL patterns yielded. Default if unspecified is the string "/".

'/'

Yields:

Type Description
str

Each URL pattern defined in the given urlconf and its descendants

Examples:

>>> generator = get_url_patterns()
>>> next(generator)
'/'
>>> next(generator)
'/search/'
>>> next(generator)
'/login/'
>>> next(generator)
'/logout/'
>>> next(generator)
'/circuits/circuits/<uuid:pk>/terminations/swap/'
>>> import example_plugin.urls as example_urls
>>> for url_pattern in get_url_patterns(example_urls, base_path="/plugins/example-app/"):
...     print(url_pattern)
...
/plugins/example-app/
/plugins/example-app/config/
/plugins/example-app/models/<uuid:pk>/dynamic-groups/
/plugins/example-app/other-models/<uuid:pk>/dynamic-groups/
/plugins/example-app/docs/
/plugins/example-app/circuits/<uuid:pk>/example-app-tab/
/plugins/example-app/devices/<uuid:pk>/example-app-tab-1/
/plugins/example-app/devices/<uuid:pk>/example-app-tab-2/
/plugins/example-app/override-target/
/plugins/example-app/^models/$
/plugins/example-app/^models/add/$
/plugins/example-app/^models/import/$
/plugins/example-app/^models/edit/$
/plugins/example-app/^models/delete/$
/plugins/example-app/^models/all-names/$
/plugins/example-app/^models/(?P<pk>[^/.]+)/$
/plugins/example-app/^models/(?P<pk>[^/.]+)/delete/$
/plugins/example-app/^models/(?P<pk>[^/.]+)/edit/$
/plugins/example-app/^models/(?P<pk>[^/.]+)/changelog/$
/plugins/example-app/^models/(?P<pk>[^/.]+)/notes/$
/plugins/example-app/^other-models/$
/plugins/example-app/^other-models/add/$
/plugins/example-app/^other-models/edit/$
/plugins/example-app/^other-models/delete/$
/plugins/example-app/^other-models/(?P<pk>[^/.]+)/$
/plugins/example-app/^other-models/(?P<pk>[^/.]+)/delete/$
/plugins/example-app/^other-models/(?P<pk>[^/.]+)/edit/$
/plugins/example-app/^other-models/(?P<pk>[^/.]+)/changelog/$
/plugins/example-app/^other-models/(?P<pk>[^/.]+)/notes/$

nautobot.apps.utils.get_view_for_model(model, view_type='')

Return the UIViewSet or <view_type>View class associated with a given model.

The view class is expected to be in the views module within the app associated with the model, and its name is expected to be either {ModelName}UIViewSet or {ModelName}{view_type}View.

If neither view class is found, this will return None.

nautobot.apps.utils.get_worker_count(request=None, queue=None)

Return a count of the active Celery workers in a specified queue. Defaults to the CELERY_TASK_DEFAULT_QUEUE setting.

nautobot.apps.utils.hex_to_rgb(hex_str)

Map a hex string like "00ff00" to individual r, g, b integer values.

nautobot.apps.utils.image_upload(instance, filename)

Return a path for uploading image attachments.

nautobot.apps.utils.is_url(value)

Validate whether a value is a URL.

Parameters:

Name Type Description Default
value str

String to validate.

required

Returns:

Type Description
bool

True if the value is a valid URL, False otherwise.

nautobot.apps.utils.lighten_color(r, g, b, factor)

Make a given RGB color lighter (closer to white).

nautobot.apps.utils.merge_dicts_without_collision(d1, d2)

Merge two dicts into a new dict, but raise a ValueError if any key exists with differing values across both dicts.

nautobot.apps.utils.migrate_content_type_references_to_new_model(apps, old_ct, new_ct)

When replacing a model, this will update references to the content type on related models such as tags and object changes.

Since this only updates the content type and not the primary key, this is typically only useful when migrating to a new model and preserving the old instance's primary key.

This will replace the old content type with the new content type on the following models
  • ComputedField.content_type
  • CustomLink.content_type
  • ExportTemplate.content_type
  • Note.assigned_object_type
  • ObjectChange.changed_object_type
  • Relationship.source_type
  • Relationship.destination_type
  • RelationshipAssociation.source_type
  • RelationshipAssociation.destination_type
  • TaggedItem.content_type

For these one-to-many and many-to-many relationships, the new content type is added to the related model's content type list, but the old content type is not removed: - CustomField.content_types - JobButton.content_types - JobHook.content_types - ObjectPermission.object_types - Status.content_types - Tag.content_types - WebHook.content_types

This will also fix tags that were not properly enforced by adding the new model's content type to the tag's content types if an instance of the new model is using the tag.

Parameters:

Name Type Description Default
apps obj

An instance of the Django 'apps' object.

required
old_ct obj

An instance of ContentType for the old model.

required
new_ct obj

An instance of ContentType for the new model.

required

nautobot.apps.utils.migrate_role_data(model_to_migrate, *, from_role_field_name, from_role_model=None, from_role_choiceset=None, to_role_field_name, to_role_model=None, to_role_choiceset=None, is_m2m_field=False)

Update all model_to_migrate with a value for to_role_field based on from_role_field values.

Parameters:

Name Type Description Default
model_to_migrate Model

Model with role fields to alter

required
from_role_field_name str

Name of the field on model_to_migrate to use as source data

required
from_role_model Model

If from_role_field is a ForeignKey or M2M field, the corresponding model for it

None
from_role_choiceset ChoiceSet

If from_role_field is a choices field, the corresponding ChoiceSet for it

None
to_role_field_name str

Name of the field on model_to_migrate to update based on the from_role_field

required
to_role_model Model

If to_role_field is a ForeignKey or M2M field, the corresponding model for it

None
to_role_choiceset ChoiceSet

If to_role_field is a choices field, the corresponding ChoiceSet for it

None
is_m2m_field bool

True if the role fields are both ManyToManyFields, else False

False

nautobot.apps.utils.normalize_querydict(querydict, form_class=None)

Convert a QueryDict to a normal, mutable dictionary, preserving list values. For example,

QueryDict('foo=1&bar=2&bar=3&baz=')

becomes:

{'foo': '1', 'bar': ['2', '3'], 'baz': ''}

This function is necessary because QueryDict does not provide any built-in mechanism which preserves multiple values.

A form_class can be provided as a way to hint which query parameters should be treated as lists.

nautobot.apps.utils.permission_is_exempt(name)

Determine whether a specified permission is exempt from evaluation.

:param name: Permission name in the format ._

nautobot.apps.utils.populate_model_features_registry(refresh=False)

Populate the registry model features with new apps.

This function updates the registry model features.

Behavior: - Defines a list of dictionaries called lookup_confs. Each dictionary contains: - 'feature_name': The name of the feature to be updated in the registry. - 'field_names': A list of names of fields that must be present in order for the model to be considered a valid model_feature. - 'field_attributes': Optional dictionary of attributes to filter the fields by. Only model which fields match all the attributes specified in the dictionary will be considered. This parameter can be useful to narrow down the search for fields that match certain criteria. For example, if field_attributes is set to {"related_model": RelationshipAssociation}, only fields with a related model of RelationshipAssociation will be considered. - Looks up all the models in the installed apps. - For each dictionary in lookup_confs, calls lookup_by_field() function to look for all models that have fields with the names given in the dictionary. - Groups the results by app and updates the registry model features for each app.

nautobot.apps.utils.refresh_job_model_from_job_class(job_model_class, job_class)

Create or update a job_model record based on the metadata of the provided job_class.

Note that job_model_class is a parameter (rather than doing a "from nautobot.extras.models import Job") because this function may be called from various initialization processes (such as the "nautobot_database_ready" signal) and in that case we need to not import models ourselves.

nautobot.apps.utils.remove_prefix_from_cf_key(field_name)

field_name (str): f"cf_{cf.key}"

Helper method to remove the "cf_" prefix

nautobot.apps.utils.render_jinja2(template_code, context)

Render a Jinja2 template with the provided context. Return the rendered content.

nautobot.apps.utils.resolve_permission(name)

Given a permission name, return the app_label, action, and model_name components. For example, "dcim.view_location" returns ("dcim", "view", "location").

:param name: Permission name in the format ._

nautobot.apps.utils.resolve_permission_ct(name)

Given a permission name, return the relevant ContentType and action. For example, "dcim.view_location" returns (Location, "view").

:param name: Permission name in the format ._

nautobot.apps.utils.rgb_to_hex(r, g, b)

Map r, g, b values to a hex string.

nautobot.apps.utils.sanitize(dirty, replacement='(redacted)')

Make an attempt at stripping potentially-sensitive information from the given string, bytes or iterable thereof.

Obviously this will never be 100% foolproof but we can at least try.

Uses settings.SANITIZER_PATTERNS as the list of (regexp, repl) tuples to apply.

nautobot.apps.utils.shallow_compare_dict(source_dict, destination_dict, exclude=None)

Return a new dictionary of the different keys. The values of destination_dict are returned. Only the equality of the first layer of keys/values is checked. exclude is a list or tuple of keys to be ignored.

nautobot.apps.utils.swap_status_initials(data)

Swap Git status initials with its equivalent.

nautobot.apps.utils.task_queues_as_choices(task_queues)

Returns a list of 2-tuples for use in the form field choices argument. Appends worker count to the description.

nautobot.apps.utils.to_meters(length, unit)

Convert the given length to meters.

nautobot.apps.utils.wrap_model_clean_methods()

Helper function that wraps plugin model validator registered clean methods for all applicable models