What's Changed
Full Changelog: v10.0.1...v11.0.0
[11.0.0] - 2026-03-02
Added
- Global assignment list view at
/plugins/netbox-attachments/netbox-attachment-assignments/with search (q) and filter by attachment, object type, and tag (issue #2). - Object detail attachment tab now renders assignments via
NetBoxAttachmentForObjectTablewith columns: Attachment, Description, File, Size, Tags, and Actions (download + Unlink per row) (issue #4). - Tags on
NetBoxAttachmentAssignment: exposed in the global assignment list table, the link form, and the filter form. - "Assignments" entry added to the plugin sidebar menu under Attachments.
NetBoxAttachmentAssignmentjunction model: one attachment can now be linked to multiple objects simultaneously.- New "Assign" / "Unlink" UI workflow: link form with HTMX-driven object picker (
NetBoxAttachmentLinkView) and unlink confirmation page (NetBoxAttachmentAssignmentDeleteView). - New API endpoint
/api/plugins/netbox-attachments/netbox-attachment-assignments/with full CRUD support; usesObjectTypeFieldto correctly resolve"app_label.model"strings to NetBoxObjectTypeproxy instances. - New filter fields:
has_assignments,has_broken_assignments,object_type_id,object_id(routed through assignment relation). - Attachment list table: "Assigned To" column shows up to 3 linked objects with a "+N more" badge; rows with no assignments highlighted with the
dangerCSS class. - Migrations 0008–0011: create assignment table, data-migrate existing FK links, remove deprecated
object_type/object_idfields fromNetBoxAttachment, add composite DB index on(object_type_id, object_id). - CI matrix extended to Python 3.14.
- Certification documentation set under
docs/. - CI workflow for tests and build validation.
- Governance documents (
CONTRIBUTING.md, certification checklist). - Standalone pytest coverage for configuration and template helper behavior.
Changed
- NetBox compatibility locked to
4.5.xin plugin runtime bounds. - Project packaging migrated to
pyproject.toml;setuptoolsminimum requirement bumped;dependenciespopulated withdjango>=5.0,<6.0; NetBox compatibility enforced at runtime viamin_version/max_version. MANIFEST.incorrected to includedocs/in sdist.- README aligned to current compatibility policy and support channels.
- Unlinking the last assignment no longer auto-deletes the attachment or its file. Attachments now persist until explicitly deleted.
ObjectTypequeryset scan now uses.only("id").iterator()for memory efficiency when resolving enabled models.- Panel display modes (
left_page,right_page,full_width_page) now render per-row Download and Unlink buttons via a dedicatedNetBoxAttachmentPanelListViewbacked byNetBoxAttachmentForObjectTable, matchingadditional_tabbehaviour. - Unlink confirmation displays
app_label > model #id(e.g.,dcim > circuit #224) instead of the ContentType verbose name (issue #3). - Redirect after unlinking the last assignment now goes to the attachment list instead of a stale attachment URL.
- Filter form boolean fields use
BooleanFieldwith an explicitSelectwidget instead ofNullBooleanField. - Exception handlers narrowed from bare
exceptclauses to specific exception types throughout. template_content.pyrender functions guard against missing request context before rendering.OSErrorwhen reading file size on save is caught;sizefield storesnullinstead of raising.CustomObjectTypeDB lookup invalidate_object_typedeferred to avoid startupRuntimeWarning.- Exception chaining suppressed in serializer
validate()for cleaner error tracebacks. - Attachment list, bulk-edit, and bulk-delete querysets now annotate
attachment_link_countviaCount("attachment__attachment_assignments", distinct=True)so assignment-count-based row highlighting works in all list contexts without extra queries; replaces the previousprefetch_relatedapproach that issued a separate round-trip and returned full rows only to count them. __init__.py:except ImportErrornarrowed toexcept ModuleNotFoundErrorfor thePluginConfigfallback.utils.py:_get_plugin_settings()also catchesImproperlyConfiguredso the helper is safe to call before Django is fully configured.NetBoxAttachmentLinkView: "Save and Add Another" now correctly detects flow direction and forwards only the relevant GET params, avoiding aValueErrorwhenobject_type/object_idwere absent.NetBoxAttachmentForObjectTable:tagscolumn added todefault_columnsso assignment tag badges are visible by default on object detail Attachments tabs and inline panels.NetBoxAttachmentForObjectTable:TagColumn.url_namecorrected tonetboxattachmentassignment_list(wasnetboxattachment_list).- Assignment querysets in
AttachmentTabView.get_children(),NetBoxAttachmentAssignmentListView, andNetBoxAttachmentPanelListViewnowprefetch_related("tags")so assignment tag badges render without N+1 queries.
Fixed
utils.py:validate_object_type()no longer raisesNameErrorwhennetbox_custom_objectsis not installed; theexcepttuple now usesObjectDoesNotExist(imported at module level) instead ofCustomObjectType.DoesNotExist, which was unresolvable after a failed import.tables.py:get_missing_parent_row_class()fallback path now emits alogger.warning()so unannotated queries are visible in server logs rather than silently issuing extra DB queries.NetBoxAttachmentLinkForm: object-type picker now filters viaget_enabled_object_type_queryset()instead of a bareObjectType.objects.get(), so only plugin-configured types are selectable after an HTMX reload.NetBoxAttachmentLinkForm: editing an existing assignment no longer raises a false "duplicate assignment" validation error;self.instance.pkis now excluded from the uniqueness check.has_assignmentsandhas_broken_assignmentsfilter fields changed fromforms.BooleanField(with aSelectwidget) toforms.ChoiceField. Django'sBooleanField.has_changed()coerces bothNoneand"false"to PythonFalse, so the field was never considered changed and the filter chip for "Has Assignments: No" / "Has Broken Assignments: No" never appeared.ChoiceFieldcompares raw strings ("" != "false"), so the chip now renders correctly.
Security
return_urlredirect targets validated withurl_has_allowed_host_and_schemebefore redirecting.- Templates updated with
rel="noopener"on external links andurlencodefilter on URL parameters.