Skip to content

# `nautobot.apps.api`

Helpers for an app to implement a REST API.

## `nautobot.apps.api.APIRootView`

Bases: `NautobotAPIVersionMixin`, `APIRootView`

Extends DRF's base APIRootView class to enforce user authentication.

## `nautobot.apps.api.BaseModelSerializer`

Bases: `OptInFieldsMixin`, `HyperlinkedModelSerializer`

This base serializer implements common fields and logic for all ModelSerializers.

Namely, it:

- defines the `display` field which exposes a human friendly value for the given object.
- ensures that `id` field is always present on the serializer as well.
- ensures that `created` and `last_updated` fields are always present if applicable to this model and serializer.
- ensures that `object_type` field is always present on the serializer which represents the content-type of this serializer's associated model (e.g. "dcim.device"). This is required as the OpenAPI schema, using the PolymorphicProxySerializer class defined below, relies upon this field as a way to identify to the client which of several possible serializers are in use for a given attribute.
- supports `?depth` query parameter. It is passed in as `nested_depth` to the `build_nested_field()` function to enable the dynamic generation of nested serializers.

### `is_nested` `property`

Return whether this is a nested serializer.

### `__init__(*args, force_csv=False, **kwargs)`

Instantiate a BaseModelSerializer.

The force_csv kwarg allows you to force _is_csv_request() to evaluate True without passing a Request object, which is necessary to be able to export appropriately structured CSV from a Job that doesn't have a Request.

### `build_field(field_name, info, model_class, nested_depth)`

Return a two tuple of (cls, kwargs) to build a serializer field with.

### `build_property_field(field_name, model_class)`

Create a property field for model methods and properties.

### `build_relational_field(field_name, relation_info)`

Override DRF's default relational-field construction to be app-aware.

### `build_url_field(field_name, model_class)`

Override DRF's default 'url' field construction to be app-aware.

### `extend_field_names(fields, field_name, at_start=False, opt_in_only=False)`

Prepend or append the given field_name to `fields` and optionally self.Meta.opt_in_fields as well.

### `get_display(instance)`

Return either the `display` property of the instance or `str(instance)`

### `get_field_names(declared_fields, info)`

Override get_field_names() to add some custom logic.

Assuming that we follow the pattern where `fields = "__all__" for the vast majority of serializers in Nautobot, we do not strictly need to use this method to protect against inadvertently omitting standard fields like`display`,`created`, and`last_updated`. However, we continue to do as a bit of redundant safety.

The other purpose of this method now is to manipulate the set of fields that "all" actually means as a way of excluding fields that we don't want to include by default for performance or data exposure reasons.

## `nautobot.apps.api.BulkDestroyModelMixin`

Support bulk deletion of objects using the list endpoint for a model. Accepts a DELETE action with a list of one or more JSON objects, each specifying the UUID of an object to be deleted. For example:

DELETE /api/dcim/locations/ [ {"id": "3f01f169-49b9-42d5-a526-df9118635d62"}, {"id": "c27d6c5b-7ea8-41e7-b9dd-c065efd5d9cd"} ]

## `nautobot.apps.api.BulkUpdateModelMixin`

Support bulk modification of objects using the list endpoint for a model. Accepts a PATCH action with a list of one or more JSON objects, each specifying the UUID of an object to be updated as well as the attributes to be set. For example:

PATCH /api/dcim/locations/ [ { "id": "1f554d07-d099-437d-8d48-7d6e35ec8fa3", "name": "New name" }, { "id": "1f554d07-d099-437d-8d48-7d6e65ec8fa3", "status": "planned" } ]

## `nautobot.apps.api.ChoiceField`

Bases: `Field`

Represent a ChoiceField as {'value': , 'label': }. Accepts a single value on write.

:param choices: An iterable of choices in the form (value, key). :param allow_blank: Allow blank values in addition to the listed choices.

## `nautobot.apps.api.ContentTypeField`

Bases: `RelatedField`

Represent a ContentType as '.'

## `nautobot.apps.api.CustomFieldModelSerializerMixin`

Bases: `ValidatedModelSerializer`

Extends ModelSerializer to render any CustomFields and their values associated with an object.

### `get_field_names(declared_fields, info)`

Ensure that "custom_fields" and "computed_fields" are included appropriately.

## `nautobot.apps.api.CustomFieldModelViewSet`

Bases: `ModelViewSet`

Include the applicable set of CustomFields in the ModelViewSet context.

## `nautobot.apps.api.ModelViewSet`

Bases: `NautobotAPIVersionMixin`, `BulkUpdateModelMixin`, `BulkDestroyModelMixin`, `ModelViewSetMixin`, `ModelViewSet`

Extend DRF's ModelViewSet to support bulk update and delete functions.

## `nautobot.apps.api.ModelViewSetMixin`

### `get_object()`

Extend rest_framework.generics.GenericAPIView.get_object to allow "pk" lookups to use a composite-key.

### `get_queryset()`

Attempt to optimize the queryset based on the fields present in the associated serializer.

See similar logic in nautobot.core.tables.BaseTable.

### `initial(request, *args, **kwargs)`

Runs anything that needs to occur prior to calling the method handler.

Override of internal Django Rest Framework API.

### `restrict_queryset(request, *args, **kwargs)`

Restrict the view's queryset to allow only the permitted objects for the given request.

Subclasses (such as nautobot.extras.api.views.JobModelViewSet) may wish to override this.

Called by initial(), below.

## `nautobot.apps.api.MultipleChoiceJSONField`

Bases: `MultipleChoiceField`

A MultipleChoiceField that renders the received value as a JSON-compatible list rather than a set.

### `__init__(**kwargs)`

Overload default choices handling to also accept a callable.

## `nautobot.apps.api.NautobotAutoSchema`

Bases: `AutoSchema`

Nautobot-specific extensions to drf-spectacular's AutoSchema.

### `is_bulk_action` `property`

Custom property for convenience.

### `is_partial_action` `property`

Custom property for convenience.

### `get_description()`

Get the appropriate description for a given API endpoint.

By default, if a specific action doesn't have its own docstring, and neither does the view class, drf-spectacular will walk up the MRO of the view class until it finds a docstring, and use that. Most of our viewsets (for better or for worse) do not have docstrings, and so it'll find and use the generic docstring of the `NautobotModelViewSet` class, which isn't very useful to the end user. Instead of doing that, we only use the docstring of the view itself (ignoring its parent class docstrings), or if none exists, we make an attempt at rendering a basically accurate default description.

### `get_filter_backends()`

Nautobot's custom bulk operations, even though they return a list of records, are NOT filterable.

### `get_operation_id()`

Extend the base method to handle Nautobot's REST API bulk operations.

Without this extension, every one of our ModelViewSet classes will result in drf-spectacular complaining about operationId collisions, e.g. between DELETE /api/dcim/devices/ and DELETE /api/dcim/devices// would both get resolved to the same "dcim_devices_destroy" operation-id and this would make drf-spectacular complain.

With this extension, the bulk endpoints automatically get a different operation-id from the non-bulk endpoints.

### `get_request_serializer()`

Return the request serializer (used for describing/parsing the request payload) for this endpoint.

We override the default drf-spectacular behavior for the case where the endpoint describes a write request with required data (PATCH, POST, PUT). In those cases we replace FooSerializer with a dynamically-defined WritableFooSerializer class in order to more accurately represent the available options on write.

We also override for the case where the endpoint is one of Nautobot's custom bulk API endpoints, which require a list of serializers as input, rather than a single one.

### `get_response_serializers()`

Return the response serializer (used for describing the response payload) for this endpoint.

We override the default drf-spectacular behavior for the case where the endpoint describes a write request to a bulk endpoint, which returns a list of serializers, rather than a single one.

### `get_serializer_ref_name(serializer)`

Get the serializer's ref_name Meta attribute if set, or else derive a ref_name automatically.

Based on drf_yasg.utils.get_serializer_ref_name().

### `get_writable_class(serializer, bulk=False)`

Given a FooSerializer instance, look up or construct a [Bulk]WritableFooSerializer class if necessary.

If no [Bulk]WritableFooSerializer class is needed, returns None instead.

### `resolve_serializer(serializer, direction, bypass_extensions=False)`

Re-add required `id` field on bulk_partial_update action.

drf-spectacular clears the `required` list for any partial serializers in its `_map_basic_serializer()`, but Nautobot bulk partial updates require the `id` field to be specified for each object to update.

## `nautobot.apps.api.NautobotCSVParser`

Bases: `BaseParser`

Counterpart to NautobotCSVRenderer - import CSV data.

### `row_elements_to_data(counter, row, serializer)`

Parse a single row of CSV data (represented as a dict) into a dict suitable for consumption by the serializer.

TODO: it would be more elegant if our serializer fields knew how to deserialize the CSV data themselves; could we then literally have the parser just return list(reader) and not need this function at all?

## `nautobot.apps.api.NautobotHyperlinkedRelatedField`

Bases: `WritableSerializerMixin`, `HyperlinkedRelatedField`

Extend HyperlinkedRelatedField to include URL namespace-awareness, add 'object_type' field, and read composite-keys.

### `__init__(*args, **kwargs)`

Override DRF's namespace-unaware default view_name logic for HyperlinkedRelatedField.

DRF defaults to '{model_name}-detail' instead of '{app_label}:{model_name}-detail'.

### `to_internal_value(data)`

Convert potentially nested representation to a model instance.

### `to_representation(value)`

Convert URL representation to a brief nested representation.

## `nautobot.apps.api.NautobotModelSerializer`

Bases: `RelationshipModelSerializerMixin`, `CustomFieldModelSerializerMixin`, `NotesSerializerMixin`, `ValidatedModelSerializer`

Base class to use for serializers based on OrganizationalModel or PrimaryModel.

Can also be used for models derived from BaseModel, so long as they support custom fields, notes, and relationships.

## `nautobot.apps.api.NautobotModelViewSet`

Bases: `NotesViewSetMixin`, `CustomFieldModelViewSet`

Base class to use for API ViewSets based on OrganizationalModel or PrimaryModel.

Can also be used for models derived from BaseModel, so long as they support Notes.

## `nautobot.apps.api.NotesSerializerMixin`

Bases: `BaseModelSerializer`

Extend Serializer with a `notes` field.

### `get_field_names(declared_fields, info)`

Ensure that fields includes "notes_url" field if applicable.

## `nautobot.apps.api.NotesViewSetMixin`

### `CreateNotePermissions`

Bases: `TokenPermissions`

As nautobot.core.api.authentication.TokenPermissions, but enforcing add_note permission.

### `notes(request, *args, **kwargs)`

API methods for returning or creating notes on an object.

### `restrict_queryset(request, *args, **kwargs)`

Apply "view" permissions on the POST /notes/ endpoint, otherwise as ModelViewSetMixin.

## `nautobot.apps.api.ObjectTypeField`

Bases: `CharField`

Represent the ContentType of this serializer's model as ".".

### `__init__(*args, read_only=True, source='*', **kwargs)`

Default read_only to True as this should never be a writable field.

### `to_representation(_value)`

Get the content-type of this serializer's model.

Implemented this way because `_value` may be None when generating the schema.

## `nautobot.apps.api.OptInFieldsMixin`

Serializer mixin that adjusts its fields based on the `include` and `exclude_m2m` query parameters in a request.

The serializer's `Meta.opt_in_fields` controls which fields are influenced by `include`.

### `fields` `property`

Dynamically adjust the dictionary of fields attributed to this serializer instance.

- Removes all serializer fields specified in `Meta.opt_in_fields` list that aren't specified in the `include` query parameter. (applies to GET requests only)
- If the `exclude_m2m` query parameter is truthy, remove all many-to-many serializer fields for performance.

As an example, if the serializer specifies that `opt_in_fields = ["computed_fields"]` but `computed_fields` is not specified in the `?include` query parameter, `computed_fields` will be popped from the list of fields.

## `nautobot.apps.api.OrderedDefaultRouter`

Bases: `DefaultRouter`

### `get_api_root_view(api_urls=None)`

Wrap DRF's DefaultRouter to return an alphabetized list of endpoints.

### `register(prefix, viewset, basename=None)`

Override DRF's BaseRouter.register() to bypass an unnecessary restriction added in version 3.15.0.

(Reference: https://github.com/encode/django-rest-framework/pull/8438)

## `nautobot.apps.api.ReadOnlyModelViewSet`

Bases: `NautobotAPIVersionMixin`, `ModelViewSetMixin`, `ReadOnlyModelViewSet`

Extend DRF's ReadOnlyModelViewSet to support queryset restriction.

## `nautobot.apps.api.RelationshipModelSerializerMixin`

Bases: `ValidatedModelSerializer`

Extend ValidatedModelSerializer with a `relationships` field.

### `get_field_names(declared_fields, info)`

Ensure that "relationships" is included as an opt-in field on root serializers.

## `nautobot.apps.api.SerializedPKRelatedField`

Bases: `PrimaryKeyRelatedField`

Extends PrimaryKeyRelatedField to return a serialized object on read. This is useful for representing related objects in a ManyToManyField while still allowing a set of primary keys to be written.

## `nautobot.apps.api.StatsSerializer`

Bases: `Serializer`

Serializer for rendering linkable statistics, e.g. related object counts for a Location.

## `nautobot.apps.api.TaggedModelSerializerMixin`

Bases: `BaseModelSerializer`

### `get_field_names(declared_fields, info)`

Ensure that 'tags' field is always present except on nested serializers.

## `nautobot.apps.api.TimeZoneSerializerField`

Bases: `TimeZoneSerializerField`

Represents a time zone as a string.

## `nautobot.apps.api.TreeModelSerializerMixin`

Bases: `BaseModelSerializer`

Add a `tree_depth` field to non-nested model serializers based on django-tree-queries.

### `get_field_names(declared_fields, info)`

Ensure that "tree_depth" is included on root serializers only, as nested objects are not annotated.

### `get_tree_depth(obj)`

The `tree_depth` is not a database field, but an annotation automatically added by django-tree-queries.

## `nautobot.apps.api.ValidatedModelSerializer`

Bases: `BaseModelSerializer`

Extends the built-in ModelSerializer to enforce calling full_clean() on a copy of the associated instance during validation. (DRF does not do this by default; see https://github.com/encode/django-rest-framework/issues/3144)

## `nautobot.apps.api.WritableNestedSerializer`

Bases: `BaseModelSerializer`

Returns a nested representation of an object on read, but accepts either the nested representation or the primary key value on write operations.

Note that subclasses will always have a read-only `object_type` field, which represents the content-type of this serializer's associated model (e.g. "dcim.device"). This is required as the OpenAPI schema, using the PolymorphicProxySerializer class defined below, relies upon this field as a way to identify to the client which of several possible nested serializers are in use for a given attribute.

## `nautobot.apps.api.WritableSerializerMixin`

WritableSerializerMixin provides the to_internal_value() function. The function provides the ability to write API requests that identify unique objects based on combinations of fields other than the primary key. e.g: "parent": { "location_type__parent": {"name": "Campus"}, "parent__name": "Campus-29" } vs "parent": "10dff139-7333-46b0-bef6-f6a5a7b5497c"

### `get_object(data, queryset)`

Retrieve an unique object based on a dictionary of data attributes and raise errors accordingly if the object is not found.

### `get_queryset_filter_params(data, queryset)`

Data could be a dictionary and an int (for the User model) or a str that represents the primary key. If it is a dictionary, we return it after remove non-filter fields. If it is a primary key, we return a dictionary object formatted like this {"pk": pk}

### `remove_non_filter_fields(filter_params)`

Make output from a WritableSerializer "round-trip" capable by automatically stripping from the data any serializer fields that do not correspond to a specific model field

### `to_internal_value(data)`

Return an object or a list of objects based on a dictionary of data attributes or an UUID.

## `nautobot.apps.api.dict_to_filter_params(d, prefix='')`

Translate a dictionary of attributes to a nested set of parameters suitable for QuerySet filtering. For example:

    {
        "name": "Foo",
        "rack": {
            "facility_id": "R101"
        }
    }

Becomes:

    {
        "name": "Foo",
        "rack__facility_id": "R101"
    }

And can be employed as filter parameters:

    Device.objects.filter(**dict_to_filter(attrs_dict))

## `nautobot.apps.api.dynamic_import(name)`

Dynamically import a class from an absolute path string

## `nautobot.apps.api.get_api_version_serializer(serializer_choices, api_version)`

Returns the serializer of an api_version

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`serializer_choices` | `tuple` | list of SerializerVersions | required
`api_version` | `str` | Request API version | required

Returns:

Type | Description
--- | ---
`Serializer` | the serializer for the api_version if found in serializer_choices else None

## `nautobot.apps.api.get_serializer_for_model(model, prefix='')`

Dynamically resolve and return the appropriate serializer for a model.

Raises:

Type | Description
--- | ---
`SerializerNotFound` | if the requested serializer cannot be located.

## `nautobot.apps.api.get_view_name(view)`

Derive the view name from its associated model, if it has one. Fall back to DRF's built-in `get_view_name`.

## `nautobot.apps.api.is_api_request(request)`

Return True of the request is being made via the REST API.

## `nautobot.apps.api.rest_api_server_error(request, *args, **kwargs)`

Handle exceptions and return a useful error message for REST API requests.

## `nautobot.apps.api.versioned_serializer_selector(obj, serializer_choices, default_serializer)`

Returns appropriate serializer class depending on request api_version, and swagger_fake_view

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`obj` | `ViewSet instance` |  | required
`serializer_choices` | `tuple` | Tuple of SerializerVersions | required
`default_serializer` | `Serializer` | Default Serializer class | required