All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- CO→CO tabs —
netbox_custom_objects.*is now a valid value for bothcombined_modelsandtyped_models. This enables tabs on Custom Object detail pages themselves: when Custom Object Type A has a field (FK or M2M) pointing to Custom Object Type B, navigating to a Type B instance shows a tab listing all Type A instances that reference it. A NetBox restart is required whenever a new Custom Object Type is added (same requirement as all typed tabs). template_override.py— prepends our templates directory to Django's filesystem loader atready()time so that ournetbox_custom_objects/customobject.htmloverride (which adds{% model_view_tabs object %}) is found before the original template.
- Tab views now accept
**kwargsin theirget()method, accommodating the extracustom_object_typeURL keyword argument present on Custom Object detail URLs. base_templatefor Custom Object model instances now correctly resolves tonetbox_custom_objects/customobject.htmlinstead of the nonexistent per-model template._inject_co_urls()appends the necessary URL patterns for CO tab views intonetbox_custom_objects.urlsat startup, enabling URL reversal for registered tabs (thenetbox_custom_objectsplugin uses a single generic view and never registers per-model URL patterns for dynamic models).
- TypeError on typed tab — removed
user=keyword argument fromCustomObjectTableinstantiation.django_tables2.Table.__init__does not accept this kwarg; it was redundant becausetable.configure(request)already applies per-user column preferences. Fixes crash on NetBox 4.5.4-Docker (netbox_custom_objects0.4.6).
- Plugin version is now defined only in
pyproject.tomland read at runtime viaimportlib.metadata.version(), eliminating the duplicate version string in__init__.py.
- Typed tabs (per-type) — each Custom Object Type gets its own tab with a full-featured list view: type-specific columns, filterset sidebar, bulk edit/delete, configure table, and HTMX pagination.
typed_modelsandtyped_weightconfig settings.- Third-party plugin model support for both tab modes.
- Renamed
modelsconfig tocombined_models;labeltocombined_label;weighttocombined_weight. - Refactored views from single
views.pytoviews/package (__init__.py,combined.py,typed.py). - Templates reorganized into
combined/andtyped/subdirectories.
- Handle missing database during startup —
register_typed_tabs()now catchesOperationalErrorandProgrammingErrorso NetBox can start even when the database is unavailable or migrations haven't run yet. - Bulk action return URL in typed tabs — uses query parameter
?return_url=onformactionfor reliable redirect.
- Templates missing from built wheel — added
[tool.setuptools.package-data]inpyproject.tomlandMANIFEST.inso HTML templates are included when installing from PyPI or a pre-built wheel (fixesTemplateDoesNotExistin Docker deployments).
- Custom Objects tab on NetBox object detail pages (Device, Site, Rack, and any configured model), showing Custom Object instances that reference the viewed object via OBJECT or MULTIOBJECT typed fields.
- Pagination using NetBox's
EnhancedPaginator; respects the user's personal per-page preference and the?per_page=NURL parameter. - Text search (
?q=) filtering results by Custom Object instance display name, Custom Object Type name, and field label. - Type filter dropdown (
?type=<slug>) to narrow results to a single Custom Object Type, populated dynamically from types present in the current result set. - Efficient badge counts — the tab badge on every detail page is computed with
COUNT(*)queries (no full object rows fetched). Full rows are loaded only when the tab itself is opened, keeping detail page loads fast even with thousands of linked custom objects. - Wildcard model registration — the
modelsplugin config setting acceptsapp_label.*to register the tab for every model in an app (e.g.dcim.*,ipam.*). - Third-party plugin model support — any installed Django app (including NetBox
plugins) can be listed in
models; Django's app registry treats them identically to built-in apps. - Default configuration:
['dcim.*', 'ipam.*', 'virtualization.*', 'tenancy.*', 'contacts.*']. - Tab is hidden automatically (
hide_if_empty=True) when no custom objects reference the viewed object. - Configurable tab label and weight — set
labelandweightinPLUGINS_CONFIGto control the tab text and position (defaults:'Custom Objects',2000). - Column sorting — clicking the Type, Object, or Field column headers sorts the table in-memory; a second click toggles direction. Sort state is preserved across filter submissions.
- Value column — shows the actual field value on each Custom Object instance: a link for OBJECT fields, or comma-separated links (truncated at 3) for MULTIOBJECT fields.
- Clickable Type column — the Type column links to the Custom Object Type detail
page when the user has
viewpermission; otherwise renders as plain text. - Permission-gated action buttons — each row has an Edit button (requires
changepermission) and a Delete button (requiresdeletepermission). Users without either permission see no action buttons. - HTMX partial updates — pagination, column sorting, search form submission, and
type-dropdown changes now swap only the table zone in-place, without a full page reload.
The URL is updated via
pushStateso links remain shareable and the browser back button restores the previous filter/page state. - Tags column — each row in the Custom Objects table now shows the tags assigned to
that Custom Object instance as colored badges. Rows with no tags display
—. - Tag filter dropdown (
?tag=<slug>) — a tag dropdown appears in the search bar whenever at least one linked Custom Object has a tag, letting users narrow the table to objects with a specific tag. Tag filtering composes with?q=,?type=, sort, and pagination. Tags are pre-fetched in bulk (prefetch_related('tags')) so there is no N+1 query cost. - Configure Table — a "Configure Table" button in the card header opens a NetBox
modal that lets authenticated users show, hide, and reorder columns (Type, Object,
Value, Field, Tags). Preferences are persisted per-user in
UserConfigundertables.CustomObjectsTabTable.columnsand respected on every subsequent page load, including HTMX partial updates. The Actions column is always visible and cannot be hidden.
- Edit/Delete return URL — after saving an edit or confirming a deletion, NetBox now redirects back to the Custom Objects tab instead of to the Custom Object list page.
- Filter state preserved on return — active filters (
?q=,?type=,?sort=,?dir=,?per_page=,?page=) are retained in the return URL so the user lands back on the same filtered/sorted view after editing or deleting a custom object.