The legacy pre-commit hook script was scheduled for removal in NetBox v4.3, as noted in the TODO comment within the file. Users should now use the pre-commit tool instead.
Adds support for PATCHing ConfigContext and ConfigContextProfile with
integer IDs for `data_source` and `data_file`.
Adds regression tests to validate assignment and API functionality.
Fixes#20933
Corrects the format string for mounting depth to include a space
between the value and the unit (`mm`) for consistency with other
measurements.
Fixes#21178
Replace `gettext()` with `gettext_lazy()` to avoid locale-dependent
model serialization (and false-positive pending migration warnings).
Also make a missing `ValidationError` message translatable and
format-safe.
Fixes#21175
PluginMenuItem and PluginMenuButton classes used mutable class-level
defaults for `permissions` and `buttons` attributes, causing permission
leakage between instances when these attributes were modified without
explicit parameters.
Changed to initialize these attributes as fresh lists per instance in
__init__ when not explicitly provided, following standard Python pattern
for avoiding mutable default arguments.
Disable reassignment of IP addresses designated as primary or OOB for
parent objects. Adds validation to block changes when an IP is marked as
the OOB IP.
Fixes#21050
This was a result of the fix for #20944 optimizing a query to only
include the `id` field with `.only(id)`. Since `Prefix.__init__()`
caches original values from other fields (`_prefix` and `_vrf_id`),
these cached values are `None` at init-time.
This might not normally be a problem, but the sequence of events in
the bug report also end up causing the `handle_prefix_saved` handler
to run, which uses an ORM lookup, (either `net_contained_or_equal`
original`net_contained`) that does not support a query argument of
`None`.
* Fix on delete cascade entity order
Since [#20708](https://github.com/netbox-community/netbox/pull/20708)
relation with a on delete RESTRICT are not deleted in the proper order.
Then the error `violate not-null constraint` occurs and breaks the
delete cascade feature.
* Revert unrelated and simplify changes
* feat(ipam): Add ASDOT notation support for ASN ranges
Introduces ASDOT notation for ASN Ranges to improve readability of large
AS numbers. Adds `start_asdot` and `end_asdot` properties, columns, and
display logic for ASN ranges in the UI.
Fixes#20309
* Wrap "ASDOT" with parentheses in column header
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Closes#20929: Require render_config permission for UI config rendering
- Modified `ObjectRenderConfigView.has_permission()` to require both view and render_config permissions
- Added `remove_permissions()` test helper to remove permissions from existing ObjectPermission objects
- Added regression tests for Device and VirtualMachine render-config permission enforcement
The `render_config` permission action was introduced in #16681 for API endpoints. This extends PR_7604_description
to the UI render-config tabs, preventing users from viewing rendered configurations without explicit permission.
* Address PR feedback
* Address PR feedback
Adds logic to handle numeric range fields in API responses by
converting them into inclusive `[low, high]` pairs for consistent
behavior. Updates test cases with `vid_ranges` fields to reflect the
changes.
Closes#20491
* Fixes#20759: Group object types by app in permission form
Modified the ObjectPermissionForm to use optgroups for organizing
object types by application. This shortens the display names (e.g.,
"permission" instead of "Authentication and Authorization | permission")
while maintaining clear organization through visual grouping.
Changes:
- Updated get_object_types_choices() to return nested optgroup structure
- Enhanced AvailableOptions and SelectedOptions widgets to handle optgroups
- Modified TypeScript moveOptions to preserve optgroup structure
- Added hover text showing full model names
- Styled optgroups with bold, padded labels
* Address PR feedback
ModuleBayTemplate.instantiate() now calls resolve_name() and resolve_label()
to properly resolve {module} placeholders, making it consistent with other
modular components like InterfaceTemplate.
When a module with nested module bays is installed (e.g., a module with SFP
bays in position "A"), the nested bay labels now correctly show "A-21" instead
of "{module}-21".
This also removes the inconsistent fix from #17436 which only handled name
resolution post-instantiation. The proper resolution now happens during
instantiation using the existing resolve methods.
* Fixes#7604: Add filter modifier dropdowns for advanced lookup operators
Implements dynamic filter modifier UI that allows users to select lookup operators
(exact, contains, starts with, regex, negation, empty/not empty) directly in filter
forms without manual URL parameter editing.
Supports filters for all scalar types and strings, as well as some
related object filters. Explicitly does not support filters on fields
that use APIWidget. That has been broken out in to follow up work.
**Backend:**
- FilterModifierWidget: Wraps form widgets with lookup modifier dropdown
- FilterModifierMixin: Auto-enhances filterset fields with appropriate lookups
- Extended lookup support: Adds negation (n), regex, iregex, empty_true/false lookups
- Field-type-aware: CharField gets text lookups, IntegerField gets comparison operators, etc.
**Frontend:**
- TypeScript handler syncs modifier dropdown with URL parameters
- Dynamically updates form field names (serial → serial__ic) on modifier change
- Flexible-width modifier dropdowns with semantic CSS classes
* Remove extraneous TS comments
* Fix import order
* Fix CircuitFilterForm inheritance
* Enable filter form modifiers on DCIM models
* Enable filter form modifiers on Tenancy models
* Enable filter form modifiers on Wireless models
* Enable filter form modifiers on IPAM models
* Enable filter form modifiers on VPN models
* Enable filter form modifiers on Virtualization models
* Enable filter form modifiers on Circuit models
* Enable filter form modifiers on Users models
* Enable filter form modifiers on Core models
* Enable filter form modifiers on Extras models
* Add ChoiceField support to FilterModifierMixin
Enable filter modifiers for single-choice ChoiceFields in addition to the
existing MultipleChoiceField support. ChoiceFields can now display modifier
dropdowns with "Is", "Is Not", "Is Empty", and "Is Not Empty" options when
the corresponding FilterSet defines those lookups.
The mixin correctly verifies lookup availability against the FilterSet, so
modifiers only appear when multiple lookup options are actually supported.
Currently most FilterSets only define 'exact' for single-choice fields, but
this change enables future FilterSet enhancements to expose additional
lookups for ChoiceFields.
* Address PR feedback: Replace global filterset mappings with registry
* Address PR feedback: Move FilterModifierMixin into base filter form classes
Incorporates FilterModifierMixin into NetBoxModelFilterSetForm and FilterForm,
making filter modifiers automatic for all filter forms throughout the application.
* Fix filter modifier form submission bug with 'action' field collision
Forms with a field named "action" (e.g., ObjectChangeFilterForm) were causing
the form.action property to be shadowed by the field element, resulting in
[object HTMLSelectElement] appearing in the URL path.
Use form.getAttribute('action') instead of form.action to reliably retrieve
the form's action URL without collision from form fields.
Fixes form submission on /core/changelog/ and any other forms with an 'action'
field using filter modifiers.
* Address PR feedback: Move FORM_FIELD_LOOKUPS to module-level constant
Extracts the field type to lookup mappings from FilterModifierMixin class
attribute to a module-level constant for better reusability.
* Address PR feedback: Refactor and consolidate field filtering logic
Consolidated field enhancement logic in FilterModifierMixin by:
- Creating QueryField marker type (CharField subclass) for search fields
- Updating FilterForm and NetBoxModelFilterSetForm to use QueryField for 'q'
- Moving all skip logic into _get_lookup_choices() to return empty list for
fields that shouldn't be enhanced
- Removing separate _should_skip_field() method
- Removing unused field_name parameter from _get_lookup_choices()
- Replacing hardcoded field name check ('q') with type-based detection
* Address PR feedback: Refactor applied_filters to use FORM_FIELD_LOOKUPS
* Address PR feedback: Rename FilterModifierWidget parameter to widget
* Fix registry pattern to use model identifiers as keys
Changed filterset registration to use model identifiers ('{app_label}.{model_name}')
as registry keys instead of form classes, matching NetBox's pattern for search indexes.
* Address PR feedback: refactor brittle test for APISelect useage
Now checks if widget is actually APISelect, rather than trying to infer
from the class name.
* Refactor register_filterset to be more generic and simple
* Remove unneeded imports left from earlier registry work
* Update app registry for new `filtersets` store
* Remove unused star import, leftover from earlier work
* Enables filter modifiers on APISelect based fields
* Support filter modifiers for ChoiceField
* Include MODIFIER_EMPTY_FALSE/_TRUE in __all__
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Fix filterset registration for doubly-registered models
* Removed explicit checks against QueryField and [Null]BooleanField
I did add them to FORM_FIELD_LOOKUPS, though, to underscore that they
were considered and are intentially empty for future devs.
* Switch to sentence case for filter pill text
* Fix applied_filters template tag to use field-type-specific lookup labelsresolves
E.g. resolves gt="after" for dates vs "greater than" for numbers
* Verifies that filter pills for exact matches (no lookup
Add test for exact lookup filter pill rendering
* Add guard for FilterModifierWidget with no lookups
* Remove comparison symbols from numeric filter labels
* Match complete tags in widget rendering test assertions
* Check all expected lookups in field enhancement tests
* Move register_filterset to netbox.plugins.registration
* Require registered filterset for filter modifier enhancements
Updates FilterModifierMixin to only enhance form fields when the
associated model has a registered filterset. This provides plugin
safety by ensuring unregistered plugin filtersets fall back to
simple filters without lookup modifiers.
Test changes:
- Create TestModel and TestFilterSet using BaseFilterSet for
automatic lookup generation
- Import dcim.filtersets to ensure Device filterset registration
- Adjust tag field expectations to match actual Device filterset
(has exact/n but not empty lookups)
* Attempt to resolve static conflicts
* Move register_filterset() back to utilities.filtersets
* Add register_filterset() to plugins documentation for filtersets
* Reorder import statements
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* feat(users): Add support for enabling/disabling Tokens
Introduce an `enabled` flag on the `Token` model to allow temporarily
revoking API tokens without deleting them. Update forms, serializers,
and views to expose the new field.
Enforce the `enabled` flag in token authentication.
Add model, API, and authentication tests for the new behavior.
Fixes#20834
* Fix authentication test
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
Apply ConfigContext to objects whose platforms descend from any
assigned platform. This aligns platform behavior with regions, site
groups, locations, and roles.
Fixes#20639
The bookmarks link was pointing to ../features/customization.md#bookmarks
but the bookmarks section is actually in ../features/user-preferences.md#bookmarks.
This fixes the broken anchor link.
* Fixes#20638: Document bulk create support in OpenAPI schema
POST operations on NetBoxModelViewSet endpoints accept both single
objects and arrays, but the schema only documented single objects.
This prevented API client generators from producing correct code.
Add explicit bulk_create_enabled flag to NetBoxModelViewSet and
update schema generation to emit oneOf for these endpoints.
* Address PR feedback
- Removed brittle serializer marking mechanism in favor of direct checks
on behavior.
- Attempted to introduce a bulk_create action and then route to it on
POST in NetBoxRouter, but ran in to several obstacles including
breaking HTTP status code reporting in the schema. Opted to simply
* Remove unused bulk_create_enabled attr
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
Add the `assigned_object_type_id` filter to `L2VPNTerminationFilterSet`
so that the "Assigned object type" filter correctly restricts L2VPN
terminations by their assigned object type, using the `ObjectType` model
for lookups.
Fixes#20844
The htmx/table.html template was unconditionally including out-of-band
(OOB) swaps for UI elements that only exist on list pages, causing
htmx:oobErrorNoTarget errors when tables were embedded on detail pages.
This change adds checks for table.embedded to conditionally exclude OOB
swaps for .total-object-count, #table_save_link, and .bulk-action-buttons
when rendering embedded tables via the htmx_table template tag.
Update references from `object_type` to `object_type_id` in forms and
fieldsets for `CustomLink` and `SavedFilter` models to match the related
field definition and the expected query parameter.
Fixes#20839
Add `object_type_id` to filter CustomFields by assigned object types.
Reorganize fieldsets to separate common attributes from type-specific
options (“Type Options”), improving usability and consistency.
Fixes#20820
Introduces `device_count`, `module_count` and `rack_count` filters to
enable queries based on the existence and count of the associated
device, module or rack instances.
Updates forms, filtersets, and GraphQL schema to support these filters,
along with tests for validation.
Fixes#19523
Use blocktrans 'with' clause to pass literal code/commands as variables,
preventing them from being translated. This fixes issues where commands
like 'manage.py collectstatic' were incorrectly translated to nonsensical
strings in non-English locales.
Updated templates:
- media_failure.html: manage.py collectstatic
- programming_error.html: python3 manage.py migrate, SELECT VERSION()
- import_error.html: requirements.txt, local_requirements.txt, pip freeze
Ensure `actions` are consistently normalized to a list of strings during
cloned object initialization. This resolves potential type mismatches
when processing user form data.
Fixes#20750
Update the log level from `warning` to `debug` when no active
configuration revision is found. This prevents unnecessary warnings in
normal operation scenarios, improving log clarity and relevance.
Fixes#20688
Introduce a new `object_type_id` filter to enhance filtering by object
type for Jobs. Update related forms and fieldsets to incorporate the
new filter for better usability and consistency.
Fixes#20653
* Establish GFKSerializerField and replace get_* methods in circuits.py
* Set read_only=True
* Apply GFKSerializerField to all matching SerializerMethodFields
* Use GFKSerializerField for ObjectChangeSerializer.changed_object and EventRuleSerializer.action_object
Updates `connect_counters` to prevent duplicate signal handlers by
using consistent `dispatch_uid` values per sender. Adds a check to
avoid reconnecting models already processed during registration.
Fixes#20697
Change this one special case to also use the same communication channel
(toast notification) and message format as all other validation errors.
The error message is kept mostly the same, just the index prefix is
removed. This allowed keeping and easily adjusting the existing
localizations of it.
Elements of the "related objects list" are passed to the
`prep_related_object_data` function before any validation takes place,
with the potential of failing with a hard error. Similar to the "related
objects not list" case explicitly validate the elements general type,
and raise a normal validation error if it isn't a dictionary.
The word "dictionary" is used here, since it is python terminology, and
is close enough to yaml's "mapping". While json calls them "objects",
their key-value syntax should make it obvious what "dictionary" means
here.
The related object fields are not covered by the form, so don't pass
any validation before trying to iterate over them and accessing their
elements. Instead of allowing a hard technical error to be raised,
explicitly check that it is indeed a list, and raise a normal validation
error if not.
The error message is chosen to be similar in format and wording to the
other existing validation errors. The used word "list" is quite
universal, and conveys the wanted meaning in the context of python,
json and yaml.
Integrate `ContactsColumnMixin` into various IPAM and VPN tables to
improve contact management. Updates table fields to include `contacts`.
Fixes#20700
Mark `can_view`, `can_add`, `can_change`, and `can_delete` columns in
the Permissions list as `orderable=False`. Sorting by these computed
flags persisted an invalid sort key which triggers a `FieldError` when
loading `/users/permissions/`.
Fixes#20655
Allow passing a FilterSet to BulkRenameView for consistent behavior with
BulkEditView and BulkDeleteView. Enables the
"Select all N matching query" functionality to expand across the full
queryset. Updates logic to handle PK lists appropriately when editing
all matched objects.
Fixes#20389
The get_view_name() utility function crashed with AttributeError when
called on viewsets that override get_queryset() without setting a
class-level queryset attribute (e.g., ObjectChangeViewSet).
This pattern became necessary in #20089 to force re-evaluation of
valid_models() on each request, ensuring ObjectChange querysets reflect
current ContentType state.
Added None check to fall back to DRF's default view naming when no
class-level queryset exists.
Introduce a view to allow users to dismiss all unread notifications with
a single action. Update the notifications' template to include a
"Dismiss all" button for enhanced usability. This addition streamlines
notification management and improves the user experience.
Fixes#20301
When script form validation fails, display error messages for fields not
in fieldsets. Fields in fieldsets show inline errors only; hidden fields
show toast notifications to provide feedback instead of failing silently.
* Closes#16681: Introduce render_config permission for configuration rendering
Add a new custom permission action `render_config` for rendering device and
virtual machine configurations via the REST API. This allows users to render
configurations without requiring the `add` permission.
Changes:
- Add permission check to RenderConfigMixin.render_config() for devices and VMs
- Update API tests to use render_config permission instead of add
- Add tests verifying permission enforcement (403 without render_config)
- Document new permission requirement in configuration-rendering.md
Note: Currently requires both render_config AND add permissions due to the
automatic POST='add' filter in BaseViewSet.initial(). Removing the add
requirement will be addressed in a follow-up commit.
* Correct permission denied message and enable translation
* Remove add permission requirement for render_config endpoint
Remove the add permission requirement from the render-config API endpoint
while maintaining token write_enabled enforcement as specified in #16681.
Changes:
- Add TokenWritePermission class to check token write ability without requiring
specific model permissions
- Override get_permissions() in RenderConfigMixin to use TokenWritePermission
instead of TokenPermissions for render_config action
- Replace queryset restriction: use render_config instead of add
- Remove add permissions from tests - render_config permission now sufficient
- Update tests to expect 404 when permission denied (NetBox standard pattern)
Per #16681: 'requirement for write permission makes sense for API calls
(because we're accepting and processing arbitrary user data), the specific
permission for creating devices does not'
* Add render_config permission to ConfigTemplate render endpoint
Extend render_config permission requirement to the ConfigTemplate render
endpoint per issue comments.
Changes:
- Add TokenWritePermission check via get_permissions() override in
ConfigTemplateViewSet
- Restrict queryset to render_config permission in render() method
- Add explicit render_config permission check
- Add tests for ConfigTemplate.render() with and without permission
- Update documentation to include ConfigTemplate endpoint
* Address PR feedback on render_config permissions
Remove redundant permission checks, add view permission enforcement via
chained restrict() calls, and rename ConfigTemplate permission action
from render_config to render for consistency.
* Address second round of PR feedback on render_config permissions
- Remove ConfigTemplate view permission check from render_config endpoint
- Add sanity check to TokenWritePermission for non-token auth
- Use named URL patterns instead of string concatenation in tests
- Remove extras.view_configtemplate from test permissions
- Add token write_enabled enforcement tests for all render endpoints
* Misc cleanup
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
Switch icons in the top-right User dropdown to Tabler’s
`dropdown-item-icon` to standardize spacing between the icon and label.
Improves readability and ensures alignment with the overall UI styling.
Fixes#20608
* Fixes#20551: Support quick-add form prefix in automatic slug generation
The slug generation logic in `reslug.ts` looks for form fields using hard-coded ID selectors like `#id_slug` and `#id_name`. In quick-add modals, Django applies a `quickadd` prefix to form fields (introduced in #20542), resulting in IDs like `#id_quickadd-slug` and `#id_quickadd-name`. The logic couldn't find these prefixed fields, so automatic slug generation failed silently in quick-add modals. This fix updates the field selectors to try both unprefixed and prefixed patterns using the nullish coalescing operator (`??`), checking for the standard field ID first and falling back to the quickadd-prefixed ID if the standard one isn't found.
* Address PR feedback
The slug generation logic required updates to support form prefixes like `quickadd`. Python-side changes
ensure `SlugField.get_bound_field()` updates the `slug-source` attribute to include the form prefix when
present, so JavaScript receives the correct prefixed field ID. `SlugWidget.__init__()` now adds a
`slug-field` class to enable selector-based field discovery. On the frontend, `reslug.ts` now uses class
selectors (`button.reslug` and `input.slug-field`) instead of ID-based lookups, eliminating the need for
fallback logic. The template was updated to use `class="reslug"` instead of `id="reslug"` on the button to
avoid ID duplication issues.
Introduce Boolean filters `assigned` and `primary` to the MACAddress
filterset, improving filtering capabilities. Update forms, tables, and
GraphQL queries to incorporate the new filters. Add tests to validate
the correct functionality.
Fixes#20399
The validation_regex field was not being enforced for URL type custom
fields. This fix adds regex validation in two places:
1. to_form_field() - Applies regex validator to form fields (UI validation)
2. validate() - Applies regex check in model validation (API/programmatic)
Note: The original issue reported UI validation only, but this fix also
adds API validation for consistency with text field behavior and to
ensure data integrity across all entry points.
When deleting stale ContentTypes during remove_stale_contenttypes, the
pre_delete signal triggers notify_object_changed(), which calls
has_feature() with the ContentType instance. For stale types (those with
no corresponding model class), model_class() returns None, which then gets
passed to issubclass() in the feature test lambda, causing a TypeError.
The previous implementation in has_feature() checked for None before
attempting ObjectType lookup. The optimization in 5ceb6a6 removed this
safety check when refactoring the ContentType code path to use direct
feature registry lookups. This restores the null check to maintain the
original behavior of returning False for stale ContentTypes.
Introduce `ContentTypeFilter` across several filtersets, including
`object_type`, `related_object_type`, `assigned_object_type`, and
`parent_object_type`. This improvement enhances filtering specificity
and aligns with existing usability standards.
Closes#20554
Introduce `ranges_to_string_list` for converting numeric ranges into a
list of readable strings. Update the `vid_ranges_list` property and
templates to use this method for better readability and maintainability.
Add related tests to ensure functionality.
Closes#20516
Commit d22246688 added form prefix support to the `GET` handler to fix
Markdown preview functionality in quick add modals. The form prefix
allows Django to properly namespace field names and IDs when rendering
forms within the quick add modal context.
However, the corresponding change was not made to the `POST` handler. This
created a mismatch where form fields were rendered with the `quickadd-`
prefix during `GET` requests, but the `POST` handler instantiated forms
without the prefix. When users submitted quick add forms, Django looked
for unprefixed field names like `address` and `status` in the `POST` data,
but the actual submitted data used prefixed names like `quickadd-address`
and `quickadd-status`. This caused validation to fail immediately with
"This field is required" errors for all required fields, making every
quick add form unusable.
The fix adds the same prefix detection logic to the `POST` handler that was
added to the `GET` handler, checking for the `_quickadd` parameter in the
query string and applying the `quickadd` prefix when present. This ensures
consistent form field naming between rendering and validation.
A regression test has been added to `MACAddressTestCase` to verify that MAC
addresses can be successfully created via the quick add modal, preventing
this issue from recurring. This test should be promoted to a template
test whenever it becomes possible to determine if a model should support
quick-add functionality.
Introduce a generic lookup for ArrayField(RangeField) that matches rows
where a scalar value is contained by any range in the array
(e.g. VLANGroup.vid_ranges).
Replace the raw-SQL helper in the VLANGroup FilterSet (`contains_vid`)
with the ORM lookup for better maintainability.
Add tests for the lookup and the FilterSet behavior.
Closes#20497
Adjusts the schema mapping for `IntegerRangeSerializer` by setting
`match_subclasses` to `True` and refining the array definition. Adds
an example field for clarity in generated OpenAPI documentation.
Fixes#20494
* fix(users): Override create_superuser to drop is_staff
Override `UserManager.create_superuser()` to strip `is_staff` from
`extra_fields` and enforce `is_superuser=True`, fixing the `TypeError`
during `createsuperuser` with the custom `User` model.
Fixes#20342
* Set alters_data=True on manager methods
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Closes#16137: Remove is_staff boolean from User model
* Remove default is_staff value from UserManager.create_user()
* Restore staff_only on MenuItem
* Introduce IsSuperuser API permission to replace IsAdminUser
* Update and improve RQ task API view tests
* Remove is_staff attribute assignment from RemoteUserBackend
Local user accounts and groups can be created in NetBox under the "Authentication" section in the "Admin" menu. This section is available only to users with the "staff" permission enabled.
Local user accounts and groups can be created in NetBox under the "Authentication" section in the "Admin" menu.
At a minimum, each user account must have a username and password set. User accounts may also denote a first name, last name, and email address. [Permissions](../permissions.md) may also be assigned to individual users and/or groups as needed.
@@ -88,7 +88,7 @@ While permissions are typically assigned to specific groups and/or users, it is
### Viewing Objects
Object-based permissions work by filtering the database query generated by a user's request to restrict the set of objects returned. When a request is received, NetBox first determines whether the user is authenticated and has been granted to perform the requested action. For example, if the requested URL is `/dcim/devices/`, NetBox will check for the `dcim.view_device` permission. If the user has not been assigned this permission (either directly or via a group assignment), NetBox will return a 403 (forbidden) HTTP response.
Object-based permissions work by filtering the database query generated by a user's request to restrict the set of objects returned. When a request is received, NetBox first determines whether the user is authenticated and has been granted permission to perform the requested action. For example, if the requested URL is `/dcim/devices/`, NetBox will check for the `dcim.view_device` permission. If the user has not been assigned this permission (either directly or via a group assignment), NetBox will return a 403 (forbidden) HTTP response.
If the permission _has_ been granted, NetBox will compile any specified constraints for the model and action. For example, suppose two permissions have been assigned to the user granting view access to the device model, with the following constraints:
@@ -102,9 +102,9 @@ If the permission _has_ been granted, NetBox will compile any specified constrai
This grants the user access to view any device that is assigned to a site named NYC1 or NYC2, **or** which has a status of "offline" and has no tenant assigned. These constraints are equivalent to the following ORM query:
!!! note "This parameter was introduced in NetBox v4.5."
Default: `1`
Designates the default version of the GraphQL API served by `/graphql/`. To access a specific version, append the version number to the URL, e.g. `/graphql/v2/`.
@@ -53,6 +53,16 @@ Sets content for the top banner in the user interface.
---
## COPILOT_ENABLED
!!! tip "Dynamic Configuration Parameter"
Default: `True`
Enables or disables the [NetBox Copilot](https://netboxlabs.com/docs/copilot/) agent globally. When enabled, users can opt to toggle the agent individually.
@@ -127,19 +127,3 @@ The list of groups that promote an remote User to Superuser on Login. If group i
Default: `[]` (Empty list)
The list of users that get promoted to Superuser on Login. If user isn't present in list on next Login, the Role gets revoked. (Requires `REMOTE_AUTH_ENABLED` and `REMOTE_AUTH_GROUP_SYNC_ENABLED` )
---
## REMOTE_AUTH_STAFF_GROUPS
Default: `[]` (Empty list)
The list of groups that promote an remote User to Staff on Login. If group isn't present on next Login, the Role gets revoked. (Requires `REMOTE_AUTH_ENABLED` and `REMOTE_AUTH_GROUP_SYNC_ENABLED` )
---
## REMOTE_AUTH_STAFF_USERS
Default: `[]` (Empty list)
The list of users that get promoted to Staff on Login. If user isn't present in list on next Login, the Role gets revoked. (Requires `REMOTE_AUTH_ENABLED` and `REMOTE_AUTH_GROUP_SYNC_ENABLED` )
!!! info "This parameter was introduced in NetBox v4.5."
[Cryptographic peppers](https://en.wikipedia.org/wiki/Pepper_(cryptography)) are employed to generate hashes of sensitive values on the server. This parameter defines the peppers used to hash v2 API tokens in NetBox. You must define at least one pepper before creating a v2 API token. See the [API documentation](../integrations/rest-api.md#authentication) for further information about how peppers are used.
Treat pepper values as extremely sensitive. Consider populating peppers from environment variables at initialization time rather than defining them in the configuration file, if feasible.
Peppers must be at least 50 characters in length and should comprise a random string with a diverse character set. Consider using the Python script at `$INSTALL_ROOT/netbox/generate_secret_key.py` to generate a pepper value.
It is recommended to start with a pepper ID of `1`. Additional peppers can be introduced later as needed to begin rotating token hashes.
!!! tip
Although NetBox will run without `API_TOKEN_PEPPERS` defined, the use of v2 API tokens will be unavailable.
The default value of this parameter changed from `True` to `False` in NetBox v4.3.0.
If disabled, the values of API tokens will not be displayed after each token's initial creation. A user **must** record the value of a token prior to its creation, or it will be lost. Note that this affects _all_ users, regardless of assigned permissions.
---
## ALLOWED_URL_SCHEMES
!!! tip "Dynamic Configuration Parameter"
@@ -92,7 +81,7 @@ If `True`, the cookie employed for cross-site request forgery (CSRF) protection
Default: `[]`
Defines a list of trusted origins for unsafe (e.g. `POST`) requests. This is a pass-through to Django's [`CSRF_TRUSTED_ORIGINS`](https://docs.djangoproject.com/en/stable/ref/settings/#csrf-trusted-origins) setting. Note that each host listed must specify a scheme (e.g. `http://` or `https://).
Defines a list of trusted origins for unsafe (e.g. `POST`) requests. This is a pass-through to Django's [`CSRF_TRUSTED_ORIGINS`](https://docs.djangoproject.com/en/stable/ref/settings/#csrf-trusted-origins) setting. Note that each host listed must specify a scheme (e.g. `http://` or `https://`).
@@ -95,7 +95,7 @@ An example fieldset definition is provided below:
```python
classMyScript(Script):
classMeta:
classMeta(Script.Meta):
fieldsets=(
('First group',('field1','field2','field3')),
('Second group',('field4','field5')),
@@ -131,17 +131,6 @@ self.log_info(f"Running as user {username} (IP: {ip_address})...")
For a complete list of available request parameters, please see the [Django documentation](https://docs.djangoproject.com/en/stable/ref/request-response/).
## Reading Data from Files
The Script class provides two convenience methods for reading data from files:
*`load_yaml`
*`load_json`
These two methods will load data in YAML or JSON format, respectively, from files within the local path (i.e. `SCRIPTS_ROOT`).
**Note:** These convenience methods are deprecated and will be removed in NetBox v4.4. These only work if running scripts within the local path, they will not work if using a storage other than ScriptFileSystemStorage.
## Logging
The Script object provides a set of convenient functions for recording messages at different severity levels:
@@ -404,6 +393,61 @@ A complete date & time. Returns a `datetime.datetime` object.
Custom scripts can be run via the web UI by navigating to the script, completing any required form data, and clicking the "run script" button. It is possible to schedule a script to be executed at specified time in the future. A scheduled script can be canceled by deleting the associated job result object.
#### Prefilling variables via URL parameters
Script form fields can be prefilled by appending query parameters to the script URL. Each parameter name must match the variable name defined on the script class. Prefilled values are treated as initial values and can be edited before execution. Multiple values can be supplied by repeating the same parameter. Query values must be percent‑encoded where required (for example, spaces as `%20`).
Examples:
For string and integer variables, when a script defines:
| `IPAddressVar` | IP address | `?ip=198.51.100.10` |
| `IPAddressWithMaskVar` | IP address with mask | `?addr=192.0.2.1/24` |
| `IPNetworkVar` | IP network prefix | `?network=2001:db8::/64` |
| `DateVar` | date `YYYY-MM-DD` | `?date=2025-01-05` |
| `DateTimeVar` | ISO datetime | `?when=2025-01-05T14:30:00` |
| `FileVar` | — (not supported) | — |
!!! note
- The parameter names above are examples; use the actual variable attribute names defined by the script.
- For `BooleanVar`, only an empty value (`?enabled=`) unchecks the box; any other value including `false` or `0` checks it.
- File uploads (`FileVar`) cannot be prefilled via URL parameters.
### Via the API
To run a script via the REST API, issue a POST request to the script's endpoint specifying the form data and commitment. For example, to run a script named `example.MyReport`, we would make a request such as the following:
@@ -20,6 +20,10 @@ A dictionary mapping data backend types to their respective classes. These are u
Stores registration made using `netbox.denormalized.register()`. For each model, a list of related models and their field mappings is maintained to facilitate automatic updates.
### `filtersets`
A dictionary mapping each model (identified by its app and label) to its filterset class, if one has been registered for it. Filtersets are registered using the `@register_filterset` decorator.
### `model_features`
A dictionary of model features (e.g. custom fields, tags, etc.) mapped to the functions used to qualify a model as supporting each feature. Model features are registered using the `register_model_feature()` function in `netbox.utils`.
| [Bookmarks](../features/customization.md#bookmarks) | `BookmarksMixin` | `bookmarks` | These models can be bookmarked natively in the user interface |
| [Bookmarks](../features/user-preferences.md#bookmarks) | `BookmarksMixin` | `bookmarks` | These models can be bookmarked natively in the user interface |
| [Change logging](../features/change-logging.md) | `ChangeLoggingMixin` | `change_logging` | Changes to these objects are automatically recorded in the change log |
| Cloning | `CloningMixin` | `cloning` | Provides the `clone()` method to prepare a copy |
| [Contacts](../features/contacts.md) | `ContactsMixin` | `contacts` | Contacts can be associated with these models |
@@ -10,9 +10,11 @@ Change records are exposed in the API via the read-only endpoint `/api/extras/ob
## User Messages
!!! info "This feature was introduced in NetBox v4.4."
When creating, modifying, or deleting an object in NetBox, a user has the option of recording an arbitrary message (up to 200 characters) that will appear in the change record. This can be helpful to capture additional context, such as the reason for a change or a reference to an external ticket.
When creating, modifying, or deleting an object in NetBox, a user has the option of recording an arbitrary message that will appear in the change record. This can be helpful to capture additional context, such as the reason for the change.
When editing an object via the web UI, the "Changelog message" field appears at the bottom of the form. This field is optional. The changelog message field is available in object create forms, object edit forms, delete confirmation dialogs, and bulk operations.
For information on including changelog messages when making changes via the REST API, see [Changelog Messages](../integrations/rest-api.md#changelog-messages).
Rendering configuration templates via the REST API requires appropriate permissions for the relevant object type:
* To render a device's configuration via `/api/dcim/devices/{id}/render-config/`, assign a permission for "DCIM > Device" with the `render_config` action.
* To render a virtual machine's configuration via `/api/virtualization/virtual-machines/{id}/render-config/`, assign a permission for "Virtualization > Virtual Machine" with the `render_config` action.
* To render a config template directly via `/api/extras/config-templates/{id}/render/`, assign a permission for "Extras > Config Template" with the `render` action.
!!! info "This feature was introduced in NetBox v4.5."
Most objects in NetBox can be assigned an owner. An owner is a set of users and/or groups who are responsible for the administration of associated objects. For example, you might designate the operations team at a site as the owner for all prefixes and VLANs deployed at that site. The users and groups assigned to an owner are referred to as its members.
!!! note
Ownership of an object should not be confused with the concept of [tenancy](./tenancy.md), which indicates the dedication of an object to a specific tenant. For instance, a tenant might represent a customer served by the object, whereas an owner typically represents a set of internal users responsible for the management of the object.
Owners can be organized into groups for easier management.
Most core objects within NetBox's data model support _tenancy_. This is the association of an object with a particular tenant to convey ownership or dependency. For example, an enterprise might represent its internal business units as tenants, whereas a managed services provider might create a tenant in NetBox to represent each of its customers.
Most core objects within NetBox's data model support _tenancy_. This is the association of an object with a particular tenant to convey assignment or dependency. For example, an enterprise might represent its internal business units as tenants, whereas a managed services provider might create a tenant in NetBox to represent each of its customers.
```mermaid
flowchart TD
@@ -19,20 +19,36 @@ Tenants can be grouped by any logic that your use case demands, and groups can b
Typically, the tenant model is used to represent a customer or internal organization, however it can be used for whatever purpose meets your needs.
Most core objects within NetBox can be assigned to particular tenant, so this model provides a very convenient way to correlate ownership across object types. For example, each of your customers might have its own racks, devices, IP addresses, circuits and so on: These can all be easily tracked via tenant assignment.
Most core objects within NetBox can be assigned to a particular tenant, so this model provides a very convenient way to correlate resource allocation across object types. For example, each of your customers might have its own racks, devices, IP addresses, circuits and so on: These can all be easily tracked via tenant assignment.
The following objects can be assigned to tenants:
*Sites
*Circuits
* Circuit groups
* Virtual circuits
* Cables
* Devices
* Virtual device contexts
* Power feeds
* Racks
* Rack reservations
*Devices
*VRFs
*Sites
*Locations
* ASNs
* ASN ranges
* Aggregates
* Prefixes
* IP ranges
* IP addresses
* VLANs
*Circuits
*VLAN groups
* VRFs
* Route targets
* Clusters
* Virtual machines
* L2VPNs
* Tunnels
* Wireless LANs
* Wireless links
Tenant assignment is used to signify the ownership of an object in NetBox. As such, each object may only be owned by a single tenant. For example, if you have a firewall dedicated to a particular customer, you would assign it to the tenant which represents that customer. However, if the firewall serves multiple customers, it doesn't *belong* to any particular customer, so tenant assignment would not be appropriate.
Tenancy represents the dedication of an object to a specific tenant. As such, each object may only be assigned to a single tenant. For example, if you have a firewall dedicated to a particular customer, you would assign it to the tenant which represents that customer. However, if the firewall serves multiple customers, it doesn't *belong* to any particular customer, so the assignment of a tenant would not be appropriate.
Before continuing, check that your installed Python version is at least 3.10:
Before continuing, check that your installed Python version is at least 3.12:
```no-highlight
python3 -V
@@ -120,6 +120,23 @@ If you are not yet sure what the domain name and/or IP address of the NetBox ins
ALLOWED_HOSTS = ['*']
```
### API_TOKEN_PEPPERS
Define at least one random cryptographic pepper, identified by a numeric ID starting at 1. This will be used to generate SHA256 checksums for API tokens.
As with [`SECRET_KEY`](#secret_key) below, you can use the `generate_secret_key.py` script to generate a random pepper:
```no-highlight
python3 ../generate_secret_key.py
```
### DATABASES
This parameter holds the PostgreSQL database configuration details. The default database must be defined; additional databases may be defined as needed e.g. by plugins.
@@ -235,10 +252,10 @@ Once NetBox has been configured, we're ready to proceed with the actual installa
sudo /opt/netbox/upgrade.sh
```
Note that **Python 3.10 or later is required** for NetBox v4.0 and later releases. If the default Python installation on your server is set to a lesser version, pass the path to the supported installation as an environment variable named `PYTHON`. (Note that the environment variable must be passed _after_ the `sudo` command.)
Note that **Python 3.12 or later is required** for NetBox v4.5 and later releases. If the default Python installation on your server is set to a lesser version, pass the path to the supported installation as an environment variable named `PYTHON`. (Note that the environment variable must be passed _after_ the `sudo` command.)
@@ -60,6 +60,3 @@ You should see output similar to the following:
If the NetBox service fails to start, issue the command `journalctl -eu netbox` to check for log messages that may indicate the problem.
Once you've verified that the WSGI workers are up and running, move on to HTTP server setup.
!!! note
There is a bug in the current stable release of gunicorn (v21.2.0) where automatic restarts of the worker processes can result in 502 errors under heavy load. (See [gunicorn bug #3038](https://github.com/benoitc/gunicorn/issues/3038) for more detail.) Users who encounter this issue may opt to downgrade to an earlier, unaffected release of gunicorn (`pip install gunicorn==20.1.0`). Note, however, that this earlier release does not officially support Python 3.11.
* `is_active` - All users must be mapped to at least this group to enable authentication. Without this, users cannot log in.
* `is_staff` - Users mapped to this group are enabled for access to the administration tools; this is the equivalent of checking the "staff status" box on a manually created user. This doesn't grant any specific permissions.
* `is_superuser` - Users mapped to this group will be granted superuser status. Superusers are implicitly granted all permissions.
If the default version of Python is not at least 3.10, you'll need to pass the path to a supported Python version as an environment variable when calling the upgrade script. For example:
@@ -80,7 +80,7 @@ Likewise, the site, rack, and device objects are located under the "DCIM" applic
The full hierarchy of available endpoints can be viewed by navigating to the API root in a web browser.
Each model generally has two views associated with it: a list view and a detail view. The list view is used to retrieve a list of multiple objects and to create new objects. The detail view is used to retrieve, update, or delete an single existing object. All objects are referenced by their numeric primary key (`id`).
Each model generally has two views associated with it: a list view and a detail view. The list view is used to retrieve a list of multiple objects and to create new objects. The detail view is used to retrieve, update, or delete a single existing object. All objects are referenced by their numeric primary key (`id`).
* `/api/dcim/devices/` - List existing devices or create a new device
* `/api/dcim/devices/123/` - Retrieve, update, or delete the device with ID 123
!!! info "This feature was introduced in NetBox v4.4."
Most objects in NetBox support [change logging](../features/change-logging.md), which generates a detailed record each time an object is created, modified, or deleted. Beginning in NetBox v4.4, users can attach a message to the change record as well. This is accomplished via the REST API by including a `changelog_message` field in the object representation.
Most objects in NetBox support [change logging](../features/change-logging.md), which generates a detailed record each time an object is created, modified, or deleted. Additionally, users can attach a message to the change record as well. This is accomplished via the REST API by including a `changelog_message` field in the object representation.
For example, the following API request will create a new site and record a message in the resulting changelog entry:
This approach works when creating, modifying, or deleting objects, either individually or in bulk.
This approach works when creating, modifying, or deleting objects, either individually or in bulk. For more information about change logging, see [Change Logging](../features/change-logging.md).
## Uploading Files
@@ -653,18 +651,22 @@ The NetBox REST API primarily employs token-based authentication. For convenienc
### Tokens
A token is a unique identifier mapped to a NetBox user account. Each user may have one or more tokens which he or she can use for authentication when making REST API requests. To create a token, navigate to the API tokens page under your user profile.
A token is a secret, unique identifier mapped to a NetBox user account. Each user may have one or more tokens which he or she can use for authentication when making REST API requests. To create a token, navigate to the API tokens page under your user profile. When creating a token, NetBox will automatically populate a randomly-generated token value.
!!! note "Tokens cannot be retrieved once created"
Once a token has been created, its plaintext value cannot be retrieved. For this reason, you must take care to securely record the token locally immediately upon its creation. If a token plaintext is lost, it cannot be recovered: A new token must be created.
By default, all users can create and manage their own REST API tokens under the user control panel in the UI or via the REST API. This ability can be disabled by overriding the [`DEFAULT_PERMISSIONS`](../configuration/security.md#default_permissions) configuration parameter.
Each token contains a 160-bit key represented as 40 hexadecimal characters. When creating a token, you'll typically leave the key field blank so that a random key will be automatically generated. However, NetBox allows you to specify a key in case you need to restore a previously deleted token to operation.
Additionally, a token can be set to expire at a specific time. This can be useful if an external client needs to be granted temporary access to NetBox.
!!! info "Restricting Token Retrieval"
The ability to retrieve the key value of a previously-created API token can be restricted by disabling the [`ALLOW_TOKEN_RETRIEVAL`](../configuration/security.md#allow_token_retrieval) configuration parameter.
#### v1 and v2 Tokens
### Restricting Write Operations
Beginning with NetBox v4.5, two versions of API token are supported, denoted as v1 and v2. Users are strongly encouraged to create only v2 tokens and to discontinue the use of v1 tokens. Support for v1 tokens will be removed in a future NetBox release.
v2 API tokens offer much stronger security. The token plaintext given at creation time is hashed together with a configured [cryptographic pepper](../configuration/required-parameters.md#api_token_peppers) to generate a unique checksum. This checksum is irreversible; the token plaintext is never stored on the server and thus cannot be retrieved even with database-level access.
#### Restricting Write Operations
By default, a token can be used to perform all actions via the API that a user would be permitted to do via the web UI. Deselecting the "write enabled" option will restrict API requests made with the token to read operations (e.g. GET) only.
@@ -681,10 +683,22 @@ It is possible to provision authentication tokens for other users via the REST A
### Authenticating to the API
An authentication token is attached to a request by setting the `Authorization` header to the string `Token` followed by a space and the user's token:
An authentication token is included with a request in its `Authorization` header. The format of the header value depends on the version of token in use. v2 tokens use the following form, concatenating the token's prefix (`nbt_`) and key with its plaintext value, separated by a period:
```
$ curl -H "Authorization: Token $TOKEN" \
Authorization: Bearer nbt_<key>.<token>
```
Legacy v1 tokens use the prefix `Token` rather than `Bearer`, and include only the token plaintext. (v1 tokens do not have a key.)
```
Authorization: Token <token>
```
Below is an example REST API request utilizing a v2 token.
@@ -21,6 +21,21 @@ The cable's operational status. Choices include:
* Planned
* Decommissioning
### Profile
!!! note "This field was introduced in NetBox v4.5."
The profile to which the cable conforms. The profile determines the mapping of termination between the two ends and enables logical tracing across complex connections, such as breakout cables. Supported profiles are listed below.
* Straight (single position)
* Straight (multi-position)
* Shuffle (2x2 MPO8)
* Shuffle (4x4 MPO8)
A single-position cable is allowed only one termination point at each end. There is no limit to the number of terminations a multi-position cable may have. Each end of a cable must have the same number of terminations, unless connected to a pass-through port or to a circuit termination.
The assignment of a cable profile is optional. If no profile is assigned, legacy tracing behavior will be preserved.
An owner is a set of users and/or groups who are responsible for the administration of certain resources within NetBox. The users and groups assigned to an owner are referred to as its members. Owner assignments are useful for indicating which parties are responsible for the administration of a particular object.
Most objects within NetBox can be assigned an owner, although this is not required.
## Fields
### Name
The owner's name.
### Group
The [group](./ownergroup.md) to which the owner is assigned. The assignment of an owner to a group is optional.
Groups are used to correlate and organize [owners](./owner.md). The assignment of an owner to a group has no bearing on the relationship of owned objects to their owners.
Additional statuses may be defined by setting `VirtualMachine.status` under the [`FIELD_CHOICES`](../../configuration/data-validation.md#field_choices) configuration parameter.
### Start on boot
The start on boot setting from the hypervisor.
!!! tip
Additional statuses may be defined by setting `VirtualMachine.start_on_boot` under the [`FIELD_CHOICES`](../../configuration/data-validation.md#field_choices) configuration parameter.
### Site & Cluster
The [site](../dcim/site.md) and/or [cluster](./cluster.md) to which the VM is assigned.
@@ -60,6 +60,13 @@ Four of the standard Python logging levels are supported:
Log entries recorded using the runner's logger will be saved in the job's log in the database in addition to being processed by other [system logging handlers](../../configuration/system.md#logging).
### Jobs running for Model instances
A Job can be executed for a specific instance of a Model.
To enable this functionality, the model must include the `JobsMixin`.
When enqueuing a Job, you can associate it with a particular instance by passing that instance to the `instance` parameter.
### Scheduled Jobs
As described above, jobs can be scheduled for immediate execution or at any later time using the `enqueue()` method. However, for management purposes, the `enqueue_once()` method allows a job to be scheduled exactly once avoiding duplicates. If a job is already scheduled for a particular instance, a second one won't be scheduled, respecting thread safety. An example use case would be to schedule a periodic task that is bound to an instance in general, but not to any event of that instance (such as updates). The parameters of the `enqueue_once()` method are identical to those of `enqueue()`.
@@ -73,9 +80,10 @@ As described above, jobs can be scheduled for immediate execution or at any late
Filter sets define the mechanisms available for filtering or searching through a set of objects in NetBox. For instance, sites can be filtered by their parent region or group, status, facility ID, and so on. The same filter set is used consistently for a model whether the request is made via the UI or REST API. (Note that the GraphQL API uses a separate filter class.) NetBox employs the [django-filters2](https://django-tables2.readthedocs.io/en/latest/) library to define filter sets.
Filter sets define the mechanisms available for filtering or searching through a set of objects in NetBox. For instance, sites can be filtered by their parent region or group, status, facility ID, and so on. The same filter set is used consistently for a model whether the request is made via the UI or REST API. (Note that the GraphQL API uses a separate filter class.) NetBox employs the [django-filter](https://django-filter.readthedocs.io/en/stable/) library to define filter sets.
## FilterSet Classes
To support additional functionality standard to NetBox models, such as tag assignment and custom field support, the `NetBoxModelFilterSet` class is available for use by plugins. This should be used as the base filter set class for plugin models which inherit from `NetBoxModel`. Within this class, individual filters can be declared as directed by the `django-filters` documentation. An example is provided below.
!!! info "New in NetBox v4.5: FilterSet Registration"
NetBox v4.5 introduced the `register_filterset()` utility function. This enables plugins to register their filtersets to receive advanced functionality, such as the automatic attachment of field-specific lookup modifiers on the filter form. Registration is optional: Unregistered filtersets will continue to work as before, but will not receive the enhanced functionality.
```python
# filtersets.py
importdjango_filters
fromnetbox.filtersetsimportNetBoxModelFilterSet
fromutilities.filtersetsimportregister_filterset
from.modelsimportMyModel
@register_filterset
classMyFilterSet(NetBoxModelFilterSet):
status=django_filters.MultipleChoiceFilter(
choices=(
@@ -27,6 +32,14 @@ class MyFilterSet(NetBoxModelFilterSet):
fields=('some','other','fields')
```
In addition to the base NetBoxModelFilterSet class, the following filterset classes are also available for subclasses of standard base models.
To utilize a filter set in a subclass of one of NetBox's generic views (such as `ObjectListView` or `BulkEditView`), define the `filterset` attribute on the view class:
@@ -42,7 +55,7 @@ class MyModelListView(ObjectListView):
filterset=MyModelFilterSet
```
To enable a filter set on a REST API endpoint, set the `filterset_class` attribute on the API view:
To enable a filter set on a REST API endpoint, set the `filterset_class` attribute on the API view:
```python
# api/views.py
@@ -55,6 +68,29 @@ class MyModelViewSet(...):
filterset_class=filtersets.MyModelFilterSet
```
### Implementing Quick Search
The `ObjectListView` has a field called Quick Search. For Quick Search to work the corresponding FilterSet has to override the `search` method that is implemented in `NetBoxModelFilterSet`. This function takes a queryset and can perform arbitrary operations on it and return it. A common use-case is to search for the given search value in multiple fields:
```python
fromdjango.db.modelsimportQ
fromnetbox.filtersetsimportNetBoxModelFilterSet
fromutilities.filtersetsimportregister_filterset
@register_filterset
classMyFilterSet(NetBoxModelFilterSet):
...
defsearch(self,queryset,name,value):
ifnotvalue.strip():
returnqueryset
returnqueryset.filter(
Q(name__icontains=value)|
Q(description__icontains=value)
)
```
The `search` method is also used by the `q` filter in `NetBoxModelFilterSet` which in turn is used by the Search field in the filters tab.
## Filter Classes
### TagFilter
@@ -69,7 +105,9 @@ This class filters `tags` using the `slug` field. For example:
```python
fromdjango_filtersimportFilterSet
fromextras.filtersimportTagFilter
fromutilities.filtersetsimportregister_filterset
@register_filterset
classMyModelFilterSet(FilterSet):
tag=TagFilter()
```
@@ -85,7 +123,9 @@ This class filters `tags` using the `id` field. For example:
NetBox provides several base form classes for use by plugins.
NetBox provides several base form classes for use by plugins. Additional form classes are also available for other standard base model classes (PrimaryModel, OrganizationalModel, and NestedGroupModel).
@@ -49,9 +59,19 @@ class MyModelForm(NetBoxModelForm):
### `NetBoxModelImportForm`
This form facilitates the bulk import of new objects from CSV, JSON, or YAML data. As with model forms, you'll need to declare a `Meta` subclass specifying the associated `model` and `fields`. NetBox also provides several form fields suitable for import various types of CSV data, listed below.
This form facilitates the bulk import of new objects from CSV, JSON, or YAML data. As with model forms, you'll need to declare a `Meta` subclass specifying the associated `model` and `fields`. NetBox also provides several form fields suitable for importing various types of CSV data, listed [below](#csv-import-fields).
**Example**
#### Subclasses
The corresponding model-specific subclasses of `NetBoxModelImportForm` are documented below.
@@ -74,7 +74,7 @@ The plugin source directory contains all the actual Python code and other resour
The `PluginConfig` class is a NetBox-specific wrapper around Django's built-in [`AppConfig`](https://docs.djangoproject.com/en/stable/ref/applications/) class. It is used to declare NetBox plugin functionality within a Python package. Each plugin should provide its own subclass, defining its name, metadata, and default and required configuration parameters. An example is below:
```python
```python title="__init__.py"
from netbox.plugins import PluginConfig
class FooBarConfig(PluginConfig):
@@ -151,7 +151,7 @@ Any additional apps must be installed within the same Python environment as NetB
An example `pyproject.toml` is below:
```
```toml title="pyproject.toml"
# See PEP 518 for the spec of this file
# https://www.python.org/dev/peps/pep-0518/
@@ -173,17 +173,30 @@ classifiers=[
'Intended Audience :: Developers',
'Natural Language :: English',
"Programming Language :: Python :: 3 :: Only",
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Programming Language :: Python :: 3.14',
]
requires-python = ">=3.10.0"
requires-python = ">=3.12.0"
```
Many of these are self-explanatory, but for more information, see the [pyproject.toml documentation](https://packaging.python.org/en/latest/specifications/pyproject-toml/).
## Compatibility Matrix
Consider adding a file named `COMPATIBILITY.md` to your plugin project root (alongside `pyproject.toml`). This file should contain a table listing the minimum and maximum supported versions of NetBox (`min_version` and `max_version`) for each release. This serves as a handy reference for users who are upgrading from a previous version of your plugin. An example is shown below:
```markdown title="COMPATIBILITY.md"
# Compatibility Matrix
| Release | Minimum NetBox Version | Maximum NetBox Version |
It is strongly recommended to create a Python [virtual environment](https://docs.python.org/3/tutorial/venv.html) for the development of your plugin, as opposed to using system-wide packages. This will afford you complete control over the installed versions of all dependencies and avoid conflict with system packages. This environment can live wherever you'd like;however, it should be excluded from revision control. (A popular convention is to keep all virtual environments in the user's home directory, e.g. `~/.virtualenvs/`.)
You can make NetBox available within this environment by creating a path file pointing to its location. This will add NetBox to the Python path upon activation. (Be sure to adjust the command below to specify your actual virtual environment path, Python version, and NetBox installation.)
@@ -325,14 +325,14 @@ class CircuitTypeType(OrganizationalObjectType):
### Change filters.py
Strawberry currently doesn't directly support django-filter, so an explicit filters.py file will need to be created. NetBox includes a new `autotype_decorator` used to automatically wrap FilterSets to reduce the required code to a minimum.
Filter classes should inherit from `netbox.graphql.filters.BaseModelFilter`.
```python title="New"
import strawberry
import strawberry_django
from circuits import filtersets, models
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
from netbox.graphql.filters import BaseModelFilter
@@ -67,6 +67,46 @@ class MyModel(ExportTemplatesMixin, TagsMixin, models.Model):
...
```
### Additional Models
In addition to the base NetBoxModel class, the following additional classes are provided for convenience.
!!! info "These model classes were added to the plugins API in NetBox v4.5."
#### PrimaryModel
PrimaryModel is the go-to class for most object types. It extends NetBoxModel with `description` and `comments` fields, and it introduces support for ownership assignment.
| `description` | No | No | A human-friendly description for the object |
#### NestedGroupModel
NestedGroupModel is used for objects which arrange into a recursive hierarchy (like regions and locations) via its self-referential `parent` foreign key.
| `parent` | No | No | The object (of the same type) under which this object is nested |
| `owner` | No | No | The object's owner |
| `description` | No | No | A human-friendly description for the object |
| `comments` | No | No | General comments |
## Database Migrations
Once you have completed defining the model(s) for your plugin, you'll need to create the database schema migrations. A migration file is essentially a set of instructions for manipulating the PostgreSQL database to support your new model, or to alter existing models. Creating migrations can usually be done automatically using Django's `makemigrations` management command. (Ensure that your plugin has been installed and enabled first, otherwise it won't be found.)
| `link` | Yes | Name of the URL path to which this menu item links |
| `link_text` | Yes | The text presented to the user |
| `permissions` | - | A list of permissions required to display this link |
| `auth_required` | - | Display only for authenticated users |
| `staff_only` | - | Display only for superusers |
| `buttons` | - | An iterable of PluginMenuButton instances to include |
!!! note "Changed in NetBox v4.5"
In releases prior to NetBox v4.5, `staff_only` restricted display of a menu item to only users with `is_staff` set to True. In NetBox v4.5, the `is_staff` flag was removed from the user model. Menu items with `staff_only` set to True are now displayed only for superusers.
@@ -27,6 +27,14 @@ Serializers are responsible for converting Python objects to JSON data suitable
The default nested representation of an object is defined by the `brief_fields` attributes under the serializer's `Meta` class. (Older versions of NetBox required the definition of a separate nested serializer.)
In addition to the base NetBoxModelSerializer class, the following serializer classes are also available for subclasses of standard base models.
To create a serializer for a plugin model, subclass `NetBoxModelSerializer` in `api/serializers.py`. Specify the model class and the fields to include within the serializer's `Meta` class.
The NetBoxTable class features dynamic configuration to allow users to change their column display and ordering preferences. To configure a table for a specific request, simply call its `configure()` method and pass the current HTTPRequest object. For example:
All UI components described here were introduced in NetBox v4.5. Be sure to set the minimum NetBox version to 4.5.0 for your plugin before incorporating any of these resources.
!!! danger "Beta Feature"
UI components are considered a beta feature, and are still under active development. Please be aware that the API for resources on this page is subject to change in future releases.
To simply the process of designing your plugin's user interface, and to encourage a consistent look and feel throughout the entire application, NetBox provides a set of components that enable programmatic UI design. These make it possible to declare complex page layouts with little or no custom HTML.
## Page Layout
A layout defines the general arrangement of content on a page into rows and columns. The layout is defined under the [view](./views.md) and declares a set of rows, each of which may have one or more columns. Below is an example layout.
```
+-------+-------+-------+
| Col 1 | Col 2 | Col 3 |
+-------+-------+-------+
| Col 4 |
+-----------+-----------+
| Col 5 | Col 6 |
+-----------+-----------+
```
The above layout can be achieved with the following declaration under a view:
```python
fromnetbox.uiimportlayout
fromnetbox.viewsimportgeneric
classMyView(generic.ObjectView):
layout=layout.Layout(
layout.Row(
layout.Column(),
layout.Column(),
layout.Column(),
),
layout.Row(
layout.Column(),
),
layout.Row(
layout.Column(),
layout.Column(),
),
)
```
!!! note
Currently, layouts are supported only for subclasses of [`generic.ObjectView`](./views.md#netbox.views.generic.ObjectView).
::: netbox.ui.layout.Layout
::: netbox.ui.layout.SimpleLayout
::: netbox.ui.layout.Row
::: netbox.ui.layout.Column
## Panels
Within each column, related blocks of content are arranged into panels. Each panel has a title and may have a set of associated actions, but the content within is otherwise arbitrary.
Plugins can define their own panels by inheriting from the base class `netbox.ui.panels.Panel`. Override the `get_context()` method to pass additional context to your custom panel template. An example is provided below.
NetBox also includes a set of panels suite for specific uses, such as display object details or embedding a table of related objects. These are listed below.
::: netbox.ui.panels.Panel
::: netbox.ui.panels.ObjectPanel
::: netbox.ui.panels.ObjectAttributesPanel
#### Object Attributes
The following classes are available to represent object attributes within an ObjectAttributesPanel. Additionally, plugins can subclass `netbox.ui.attrs.ObjectAttribute` to create custom classes.
| `netbox.ui.attrs.AddressAttr` | A physical or mailing address. |
| `netbox.ui.attrs.BooleanAttr` | A boolean value |
| `netbox.ui.attrs.ColorAttr` | A color expressed in RGB |
| `netbox.ui.attrs.ChoiceAttr` | A selection from a set of choices |
| `netbox.ui.attrs.GPSCoordinatesAttr` | GPS coordinates (latitude and longitude) |
| `netbox.ui.attrs.ImageAttr` | An attached image (displays the image) |
| `netbox.ui.attrs.NestedObjectAttr` | A related nested object |
| `netbox.ui.attrs.NumericAttr` | An integer or float value |
| `netbox.ui.attrs.RelatedObjectAttr` | A related object |
| `netbox.ui.attrs.TemplatedAttr` | Renders an attribute using a custom template |
| `netbox.ui.attrs.TextAttr` | A string (text) value |
| `netbox.ui.attrs.TimezoneAttr` | A timezone with annotated offset |
| `netbox.ui.attrs.UtilizationAttr` | A numeric value expressed as a utilization graph |
::: netbox.ui.panels.OrganizationalObjectPanel
::: netbox.ui.panels.NestedGroupObjectPanel
::: netbox.ui.panels.CommentsPanel
::: netbox.ui.panels.JSONPanel
::: netbox.ui.panels.RelatedObjectsPanel
::: netbox.ui.panels.ObjectsTablePanel
::: netbox.ui.panels.TemplatePanel
::: netbox.ui.panels.PluginContentPanel
## Panel Actions
Each panel may have actions associated with it. These render as links or buttons within the panel header, opposite the panel's title. For example, a common use case is to include an "Add" action on a panel which displays a list of objects. Below is an example of this.
@@ -10,6 +10,14 @@ Minor releases are published in April, August, and December of each calendar yea
This page contains a history of all major and minor releases since NetBox v2.0. For more detail on a specific patch release, please see the release notes page for that specific minor release.
* Background Jobs for Bulk Operations ([#19589](https://github.com/netbox-community/netbox/issues/19589), [#19891](https://github.com/netbox-community/netbox/issues/19891))
* [#20953](https://github.com/netbox-community/netbox/issues/20953) - Show reverse bridge relationships on interface detail pages
* [#21071](https://github.com/netbox-community/netbox/issues/21071) - Include request method & URL when displaying server errors
### Bug Fixes
* [#19506](https://github.com/netbox-community/netbox/issues/19506) - Add filter forms for component templates to ensure object selector support
* [#20044](https://github.com/netbox-community/netbox/issues/20044) - Fix dark mode support for rack elevations
* [#20320](https://github.com/netbox-community/netbox/issues/20320) - Restore support for selecting related interfaces when bulk editing device interfaces
* [#20817](https://github.com/netbox-community/netbox/issues/20817) - Re-enable sync button when disabling scheduled syncing for a data source
* [#21045](https://github.com/netbox-community/netbox/issues/21045) - Fix `ValueError` exception when saving a site with an assigned prefix
* [#21049](https://github.com/netbox-community/netbox/issues/21049) - Ignore stale custom field data when validating an object
* [#21063](https://github.com/netbox-community/netbox/issues/21063) - Check for duplicate choice values when validating a custom field choice set
* [#21064](https://github.com/netbox-community/netbox/issues/21064) - Ensures that extra choices in custom field choice sets preserve escaped colons
---
## v4.4.9 (2025-12-23)
### Enhancements
* [#20309](https://github.com/netbox-community/netbox/issues/20309) - Support ASDOT notation for ASN ranges
* [#20720](https://github.com/netbox-community/netbox/issues/20720) - Add Latvian translations
* [#20900](https://github.com/netbox-community/netbox/issues/20900) - Allow filtering custom choice fields by multiple values in the UI
### Bug Fixes
* [#17976](https://github.com/netbox-community/netbox/issues/17976) - Remove `devicetype_count` from nested manufacturer to correct OpenAPI schema
* [#20011](https://github.com/netbox-community/netbox/issues/20011) - Provide a clear message when encountering duplicate object IDs during bulk import
* [#20114](https://github.com/netbox-community/netbox/issues/20114) - Preserve `parent_bay` during device bulk import when tags are present
* [#20491](https://github.com/netbox-community/netbox/issues/20491) - Improve handling of numeric ranges in tests
* [#20873](https://github.com/netbox-community/netbox/issues/20873) - Fix `AttributeError` exception triggered by event rules associated with an object that supports file attachments
* [#20875](https://github.com/netbox-community/netbox/issues/20875) - Ensure that parent object relations are cached (for filtering) on device/module components during instantiation
* [#20876](https://github.com/netbox-community/netbox/issues/20876) - Allow editing an IP address that resides within a range marked as populated
* [#20912](https://github.com/netbox-community/netbox/issues/20912) - Fix inconsistent clearing of `module` field on ModuleBay
* [#20944](https://github.com/netbox-community/netbox/issues/20944) - Ensure cached scope is updated on child objects when a parent region/site/location is changed
* [#20948](https://github.com/netbox-community/netbox/issues/20948) - Handle the deletion of related objects with `on_delete=RESTRICT` the same as `CASCADE`
* [#20969](https://github.com/netbox-community/netbox/issues/20969) - Fix querying of front port templates by `rear_port_id`
* [#21011](https://github.com/netbox-community/netbox/issues/21011) - Avoid writing to the database when loading active ConfigRevision
* [#21032](https://github.com/netbox-community/netbox/issues/21032) - Avoid SQL subquery in RestrictedQuerySet where unnecessary
---
## v4.4.8 (2025-12-09)
### Enhancements
* [#20068](https://github.com/netbox-community/netbox/issues/20068) - Support the assignment of module type profile attributes via bulk import
* [#20914](https://github.com/netbox-community/netbox/issues/20914) - Enable filtering device components by tenant assigned to device
### Bug Fixes
* [#19918](https://github.com/netbox-community/netbox/issues/19918) - Fix support for `{module}` resolution of components of child modules
* [#20759](https://github.com/netbox-community/netbox/issues/20759) - Improve legibility of object types in permissions form
* [#20860](https://github.com/netbox-community/netbox/issues/20860) - Ensure user-provided changelog message is recorded when creating device components via the UI
* [#20878](https://github.com/netbox-community/netbox/issues/20878) - Use the active database connection when executing custom scripts
* [#20888](https://github.com/netbox-community/netbox/issues/20888) - Resolve warnings about non-decimal values for min/max latitude & longitude fields
---
## v4.4.7 (2025-11-25)
### Enhancements
* [#20371](https://github.com/netbox-community/netbox/issues/20371) - Add Molex Micro-Fit 2x3 for power ports & power outlets
* [#20432](https://github.com/netbox-community/netbox/issues/20432) - Fix tracing of cables across multiple circuits in parallel
* [#20465](https://github.com/netbox-community/netbox/issues/20465) - Ensure that scripts are updated immediately when a new file is uploaded
* [#20638](https://github.com/netbox-community/netbox/issues/20638) - Correct OpenAPI schema for bulk create operations
* [#20649](https://github.com/netbox-community/netbox/issues/20649) - Enforce view permissions on REST API endpoint for custom scripts
* [#20740](https://github.com/netbox-community/netbox/issues/20740) - Ensure permissions constraints are enforced when executing custom scripts via the REST API
* [#20743](https://github.com/netbox-community/netbox/issues/20743) - Pass request context to custom script when triggered by an event rule
* [#20766](https://github.com/netbox-community/netbox/issues/20766) - Fix inadvertent translations on server error page
* [#20378](https://github.com/netbox-community/netbox/issues/20378) - Prevent exception when attempting to delete a data source utilized by a custom script
* [#20645](https://github.com/netbox-community/netbox/issues/20645) - CSVChoiceField should defer to model field's default value when CSV field is empty
* [#20647](https://github.com/netbox-community/netbox/issues/20647) - Improve handling of empty strings during bulk imports
* [#20653](https://github.com/netbox-community/netbox/issues/20653) - Fix filtering of jobs by object type ID
* [#20660](https://github.com/netbox-community/netbox/issues/20660) - Optimize loading of custom script modules from remote storage
* [#20670](https://github.com/netbox-community/netbox/issues/20670) - Improve validation of related objects during bulk import
* [#20688](https://github.com/netbox-community/netbox/issues/20688) - Suppress non-harmful "No active configuration revision found" warning message
* [#20697](https://github.com/netbox-community/netbox/issues/20697) - Prevent duplication of signals which increment/decrement related object counts
* [#20699](https://github.com/netbox-community/netbox/issues/20699) - Ensure proper ordering of changelog entries resulting from cascading deletions
* [#20713](https://github.com/netbox-community/netbox/issues/20713) - Ensure a pre-change snapshot is recorded on virtual chassis members being added/removed
* [#20721](https://github.com/netbox-community/netbox/issues/20721) - Fix breadcrumb navigation links in UI for background tasks
* [#20738](https://github.com/netbox-community/netbox/issues/20738) - Deleting a virtual chassis should nullify the `vc_position` of all former members
* [#20750](https://github.com/netbox-community/netbox/issues/20750) - Fix cloning of permissions when only one action is enabled
* [#20755](https://github.com/netbox-community/netbox/issues/20755) - Prevent duplicate results under certain conditions when filtering providers
* [#20771](https://github.com/netbox-community/netbox/issues/20771) - Comments are required when creating a new journal entry
* [#20774](https://github.com/netbox-community/netbox/issues/20774) - Bulk action button labels should be translated
---
## v4.4.5 (2025-10-28)
### Enhancements
* [#19751](https://github.com/netbox-community/netbox/issues/19751) - Disable occupied module bays in form dropdowns when installing a new module
* [#20301](https://github.com/netbox-community/netbox/issues/20301) - Add a "dismiss all" option to the notifications dropdown
* [#20399](https://github.com/netbox-community/netbox/issues/20399) - Add `assigned` and `primary` boolean filters for MAC addresses
* [#20567](https://github.com/netbox-community/netbox/issues/20567) - Add contacts column to services table
* [#20422](https://github.com/netbox-community/netbox/issues/20422) - Enable filtering of aggregates and prefixes by family in GraphQL API
* [#20459](https://github.com/netbox-community/netbox/issues/20459) - Fix validation of `is_oob` & `is_primary` fields under IP address bulk import
* [#20466](https://github.com/netbox-community/netbox/issues/20466) - Fix querying of devices with a primary IP assigned in GraphQL API
* [#20498](https://github.com/netbox-community/netbox/issues/20498) - Enforce the validation regex (if set) for custom URL fields
* [#20524](https://github.com/netbox-community/netbox/issues/20524) - Raise a validation error when attempting to schedule a custom script for a past date/time
* [#20541](https://github.com/netbox-community/netbox/issues/20541) - Fix resolution of GraphQL object fields which rely on custom filters
* [#20551](https://github.com/netbox-community/netbox/issues/20551) - Fix automatic slug generation in quick-add UI form
* [#20606](https://github.com/netbox-community/netbox/issues/20606) - Enable copying of values from table columns rendered as badges
* [#20641](https://github.com/netbox-community/netbox/issues/20641) - Fix `AttributeError` exception raised by the object changes REST API endpoint
* [#20646](https://github.com/netbox-community/netbox/issues/20646) - Prevent cables from connecting to objects marked as connected
* [#20655](https://github.com/netbox-community/netbox/issues/20655) - Fix `FieldError` exception when attempting to sort permissions list by actions
---
## v4.4.4 (2025-10-15)
### Bug Fixes
* [#20554](https://github.com/netbox-community/netbox/issues/20554) - Fix generic relation filters to accept `<app>.<model>` format matching POST requests
* [#20574](https://github.com/netbox-community/netbox/issues/20574) - Fix excessive storage initialization overhead when listing scripts with remote backends
* [#20584](https://github.com/netbox-community/netbox/issues/20584) - Enforce PoE mode requirement on interface templates when PoE type is set
* [#20585](https://github.com/netbox-community/netbox/issues/20585) - Fix API schema generation crash for models with single-field UniqueConstraints
* [#20587](https://github.com/netbox-community/netbox/issues/20587) - Fix upgrade.sh failure when removing stale content types
---
## v4.4.3 (2025-10-14)
### Enhancements
* [#20426](https://github.com/netbox-community/netbox/issues/20426) - Add a copy-to-clipboard button for custom script output
* [#20516](https://github.com/netbox-community/netbox/issues/20516) - Improve rendering of VLAN ID ranges in VLAN group tables
### Bug Fixes
* [#19302](https://github.com/netbox-community/netbox/issues/19302) - Fix uniqueness validation in REST API for nullable fields
* [#19615](https://github.com/netbox-community/netbox/issues/19615) - Fix support for static file parameters in templates when external storage is in use
* [#19818](https://github.com/netbox-community/netbox/issues/19818) - Hide primary IP assignment fields when creating a new virtual machine in the UI
* [#19825](https://github.com/netbox-community/netbox/issues/19825) - Prevent cache for config revisions from being erroneously overwritten when debugging is enabled
* [#20140](https://github.com/netbox-community/netbox/issues/20140) - Changing a site's region or group should update any associated circuit terminations
* [#20156](https://github.com/netbox-community/netbox/issues/20156) - Fix display of rack elevation labels
* [#20290](https://github.com/netbox-community/netbox/issues/20290) - Fix migration error when upgrading to NetBox v4.4 from releases earlier than v4.3
* [#20471](https://github.com/netbox-community/netbox/issues/20471) - Saving an unmodified VLAN group should not generate a change record
* [#20475](https://github.com/netbox-community/netbox/issues/20475) - Collapse singleton VLAN IDs in VLAN group display
* [#20494](https://github.com/netbox-community/netbox/issues/20494) - Correct OpenAPI schema definition for `IntegerRangeSerializer`
* [#20496](https://github.com/netbox-community/netbox/issues/20496) - REST API should always honor `MAX_PAGE_SIZE` value
* [#20497](https://github.com/netbox-community/netbox/issues/20497) - Fix filtering of VLAN groups by VLAN ID range in GraphQL API
* [#20507](https://github.com/netbox-community/netbox/issues/20507) - Fix support for fetching ASN contacts via GraphQL API
* [#20523](https://github.com/netbox-community/netbox/issues/20523) - Hide password change form for users authenticated via SSO
* [#20542](https://github.com/netbox-community/netbox/issues/20542) - Fix the creation of MAC addresses using the "quick add" form
* Python 3.10 and 3.11 are no longer supported. NetBox now requires Python 3.12, 3.13, or 3.14.
* GraphQL API queries which filter by object IDs or enums must now specify a filter lookup similar to other fields. For example, `id: 123` becomes `id: {exact: 123 }`.
* Rendering a device or virtual machine configuration is now restricted to users with the `render_config` permission for the applicable object type.
* Retrieval of API token plaintexts is no longer supported. The `ALLOW_TOKEN_RETRIEVAL` config parameter has been removed.
* API tokens can no longer be reassigned from one user to another.
* A config context assigned to a platform will now also apply to any children of that platform. (Although this is typically desired behavior, it may introduce unanticipated changes for existing deployments.)
* The `/api/dcim/cable-terminations/` REST API endpoint is now read-only. Cable terminations must be set on cables directly via the `/api/dcim/cables/` endpoint.
* The UI view dedicated to swapping A/Z circuit terminations has been removed.
* The experimental HTMX navigation feature has been removed.
* The obsolete boolean field `is_staff` has been removed from the `User` model.
* Removal of deprecated behavior
* The `/api/extras/object-types/` REST API endpoint has been removed. (Use `/api/core/object-types/` instead.)
* Webhooks no longer specify a `model` in payload data. (Reference `object_type` instead, which includes the parent app label.)
* The obsolete module `core.models.contenttypes` has been removed (replaced in v4.4 by `core.models.object_types`).
* The `load_yaml()` and `load_json()` utility methods have been removed from the base class for custom scripts.
### New Features
#### Lookup Modifiers in Filter Forms ([#7604](https://github.com/netbox-community/netbox/issues/7604))
Most object list filters within the UI have been extended to include optional lookup modifiers to support more complex queries. For instance, filters for numeric values now include a dropdown where a user can select "less than," "greater than," or "not" in addition to the default equivalency match. The specific modifiers available depend on the type of each filter. Plugins can register their own filtersets using the `register_filterset()` decorator to enable this new functionality.
(Note that this feature does not introduce any new filters. Rather, it makes available in the UI filters which already exist.)
#### Improved API Authentication Tokens ([#20210](https://github.com/netbox-community/netbox/issues/20210))
This release introduces a new version of API token (v2) which implements several security improvements. HMAC hashing with a cryptographic pepper is used to authenticate these tokens, obviating the need to store plaintexts. The new tokens also employ a non-sensitive key which can be shared to identify tokens without divulging their plaintexts. We've also adopted the standard "bearer" HTTP header format, as shown below.
```
# v1 token header
Authorization: Token <TOKEN>
# v2 token header
Authorization: Bearer nbt_<KEY>.<TOKEN>
```
Note that v2 token keys are prefixed with the fixed string `nbt_`, which can be used to aid in secret detection.
Backward compatibility with legacy (v1) tokens is retained in this release. However, users are strongly encouraged to begin using only v2 tokens, as support for legacy tokens will be removed in NetBox v4.7.
An optional `owner` foreign key field has been added to most models. This enables the assignment of objects to a new Owner model, which represents a set of users and/or groups. Through this relationship, we can now convey ownership of objects within NetBox natively, without needing to rely on the assignment of tags or custom fields.
(Note that ownership differs significantly in function from tenancy. Ownership determines the parties responsible for the maintenance of an object, whereas as tenancy conveys an operational dependency.)
#### Advanced Port Mappings ([#20564](https://github.com/netbox-community/netbox/issues/20564))
The previous many-to-one mapping of front to rear ports has been expanded to support bidirectional mappings. The `rear_port` and `rear_port_position` fields on the FrontPort model have been replaced with an intermediary PortMapping model, which supports any number of assignments between front port/position pair and a rear port/position pair. This change unlocks the ability to model complex inline devices that swap individual fiber pairs between cables.
Cables can now be assigned profiles which determine how they are treated for path tracing. A profile indicates the number of discrete parallel channels or lanes carried by the cable among its endpoints. For example, a 1-to-4 breakout cable has four lanes, shared at one end via a common termination and split out at the other end to four separate terminations. Profiles, when assigned, enable NetBox to more accurately trace a specific connection within a cable, rather than the cable as a whole.
The assignment of cable profiles is optional: Cable tracing will continue to operate as before for cables with no profile assigned.
### Enhancements
* [#16681](https://github.com/netbox-community/netbox/issues/16681) - Introduce a `render_config` permission, which is now required to render a device or virtual machine configuration
* [#18658](https://github.com/netbox-community/netbox/issues/18658) - Add a `start_on_boot` choice field for virtual machines
* [#19095](https://github.com/netbox-community/netbox/issues/19095) - Add support for Python 3.13 and 3.14
* [#19338](https://github.com/netbox-community/netbox/issues/19338) - Enable filter lookups for object IDs and enums in GraphQL API queries
* [#19523](https://github.com/netbox-community/netbox/issues/19523) - Cache the number of instances for device, module, and rack types, and enable filtering by these counts
* [#20417](https://github.com/netbox-community/netbox/issues/20417) - Add an optional `color` field for device type power outlets
* [#20476](https://github.com/netbox-community/netbox/issues/20476) - Once provisioned, the owner of an API token cannot be changed
* [#20492](https://github.com/netbox-community/netbox/issues/20492) - Completely disabled the means to retrieve legacy API token plaintexts (removed the `ALLOW_TOKEN_RETRIEVAL` config parameter)
* [#20639](https://github.com/netbox-community/netbox/issues/20639) - Apply config contexts to devices/VMs assigned any child platform of the parent platform
* [#20834](https://github.com/netbox-community/netbox/issues/20834) - Add an `enabled` boolean field to API tokens
* [#20917](https://github.com/netbox-community/netbox/issues/20917) - Include usage reference on API token views
* [#20925](https://github.com/netbox-community/netbox/issues/20925) - Add optional `comments` field to all subclasses of `OrganizationalModel`
* [#20929](https://github.com/netbox-community/netbox/issues/20929) - Require the `render_config` permission to view a rendered device/VM configuration in the UI
* [#20936](https://github.com/netbox-community/netbox/issues/20936) - Introduce the `/api/authentication-check/` REST API endpoint for validating authentication tokens
* [#20959](https://github.com/netbox-community/netbox/issues/20959) - Include a count of related module types for a manufacturer in the REST API
### Plugins
* [#13182](https://github.com/netbox-community/netbox/issues/13182) - Added `PrimaryModel`, `OrganizationalModel`, and `NestedGroupModel` to the plugins API, as well as their respective base classes for various resources
### Other Changes
* [#16137](https://github.com/netbox-community/netbox/issues/16137) - Remove the obsolete boolean field `is_staff` from the `User` model
* [#17571](https://github.com/netbox-community/netbox/issues/17571) - Remove the experimental HTMX navigation feature
* [#17936](https://github.com/netbox-community/netbox/issues/17936) - Introduce a dedicated `GFKSerializerField` for representing generic foreign keys in API serializers
* [#19889](https://github.com/netbox-community/netbox/issues/19889) - Drop support for Python 3.10 and 3.11
* [#19898](https://github.com/netbox-community/netbox/issues/19898) - Remove the obsolete REST API endpoint `/api/extras/object-types/`
* [#20088](https://github.com/netbox-community/netbox/issues/20088) - Remove the non-deterministic `model` key from webhook payload data
* [#20095](https://github.com/netbox-community/netbox/issues/20095) - Remove the obsolete module `core.models.contenttypes`
* [#20096](https://github.com/netbox-community/netbox/issues/20096) - Remove the `load_yaml()` and `load_json()` utility methods from the `BaseScript` class
* [#20204](https://github.com/netbox-community/netbox/issues/20204) - Started migrating object views from custom HTML templates to declarative layouts
* [#20295](https://github.com/netbox-community/netbox/issues/20295) - Cable terminations may be modified via the REST API only by modifying the cable itself
* [#20617](https://github.com/netbox-community/netbox/issues/20617) - Introduce `BaseModel` as the global base class for models
* [#20683](https://github.com/netbox-community/netbox/issues/20683) - Remove the UI view dedicated to swapping A/Z circuit terminations
* [#20926](https://github.com/netbox-community/netbox/issues/20926) - Standardize naming of GraphQL filters
### REST API Changes
* Most objects now include an optional `owner` foreign key field.
* The `/api/dcim/cable-terminations` endpoint is now read-only.
* Introduced the `/api/authentication-check/` endpoint to test REST API credentials
*`circuits.CircuitGroup`
* Add optional `comments` field
*`circuits.CircuitType`
* Add optional `comments` field
*`circuits.VirtualCircuitType`
* Add optional `comments` field
*`dcim.Cable`
* Add the optional `profile` choice field
*`dcim.FrontPort`
* Removed the `rear_port` and `rear_port_position` fields
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.