From a8e2e50447f7579ecf5f894cbff2d5a3cb5070de Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 2 Apr 2026 12:54:14 -0400 Subject: [PATCH] Yet more cleanup --- netbox/circuits/ui/panels.py | 10 +++------- netbox/netbox/ui/actions.py | 28 ++++++++++++++++++++-------- netbox/netbox/ui/panels.py | 13 ++++++++----- netbox/wireless/ui/panels.py | 6 +++--- 4 files changed, 34 insertions(+), 23 deletions(-) diff --git a/netbox/circuits/ui/panels.py b/netbox/circuits/ui/panels.py index 2ad39bca7..7f86db88f 100644 --- a/netbox/circuits/ui/panels.py +++ b/netbox/circuits/ui/panels.py @@ -13,13 +13,9 @@ class CircuitCircuitTerminationPanel(panels.ObjectPanel): template_name = 'circuits/panels/circuit_circuit_termination.html' title = _('Termination') - def __init__(self, accessor=None, side=None, **kwargs): - super().__init__(**kwargs) - - if accessor is not None: - self.accessor = accessor - if side is not None: - self.side = side + def __init__(self, side, accessor=None, **kwargs): + super().__init__(accessor=accessor, **kwargs) + self.side = side def get_context(self, context): return { diff --git a/netbox/netbox/ui/actions.py b/netbox/netbox/ui/actions.py index b87c25baa..62b3e86bf 100644 --- a/netbox/netbox/ui/actions.py +++ b/netbox/netbox/ui/actions.py @@ -118,19 +118,31 @@ class AddObject(LinkAction): url_params (dict): A dictionary of arbitrary URL parameters to append to the resolved URL """ def __init__(self, model, url_params=None, **kwargs): - # Resolve the model class from its app.name label - try: - app_label, model_name = model.split('.') - model = apps.get_model(app_label, model_name) - except (ValueError, LookupError): + # Validate the model label format + if '.' not in model: raise ValueError(f"Invalid model label: {model}") - view_name = get_viewname(model, 'add') + self.model_label = model kwargs.setdefault('label', _('Add')) kwargs.setdefault('button_icon', 'plus-thick') - kwargs.setdefault('permissions', [get_permission_for_model(model, 'add')]) - super().__init__(view_name=view_name, url_params=url_params, **kwargs) + # Defer model resolution; view_name and permissions are resolved at render time + super().__init__(view_name=None, url_params=url_params, **kwargs) + + @property + def model(self): + try: + return apps.get_model(self.model_label) + except LookupError: + raise ValueError(f"Invalid model label: {self.model_label}") + + def get_url(self, context): + self.view_name = get_viewname(self.model, 'add') + return super().get_url(context) + + def render(self, context): + self.permissions = [get_permission_for_model(self.model, 'add')] + return super().render(context) class CopyContent(PanelAction): diff --git a/netbox/netbox/ui/panels.py b/netbox/netbox/ui/panels.py index 3ee49b6a2..10de8cddf 100644 --- a/netbox/netbox/ui/panels.py +++ b/netbox/netbox/ui/panels.py @@ -78,7 +78,7 @@ class Panel: Determines whether the panel should render on the page. (Default: True) Parameters: - context (dict): The template context + context (dict): The panel's prepared context (the return value of get_context()) """ return True @@ -245,7 +245,7 @@ class CommentsPanel(ObjectPanel): ctx = super().get_context(context) return { **ctx, - 'comments': getattr(ctx['object'], self.field_name), + 'comments': getattr(ctx['object'], self.field_name, None), } @@ -270,7 +270,7 @@ class JSONPanel(ObjectPanel): ctx = super().get_context(context) return { **ctx, - 'data': getattr(ctx['object'], self.field_name), + 'data': getattr(ctx['object'], self.field_name, None), 'field_name': self.field_name, } @@ -372,10 +372,11 @@ class TextCodePanel(ObjectPanel): self.show_sync_warning = show_sync_warning def get_context(self, context): + ctx = super().get_context(context) return { - **super().get_context(context), + **ctx, 'show_sync_warning': self.show_sync_warning, - 'value': getattr(context.get('object'), self.field_name, None), + 'value': getattr(ctx['object'], self.field_name, None), } @@ -391,6 +392,8 @@ class PluginContentPanel(Panel): self.method = method def render(self, context): + if not self.should_render(context): + return '' obj = context.get('object') return _get_registered_content(obj, self.method, context) diff --git a/netbox/wireless/ui/panels.py b/netbox/wireless/ui/panels.py index 82fbaf51d..0135fe4bb 100644 --- a/netbox/wireless/ui/panels.py +++ b/netbox/wireless/ui/panels.py @@ -34,10 +34,10 @@ class WirelessLinkInterfacePanel(panels.ObjectPanel): self.title = title def get_context(self, context): - obj = context['object'] + ctx = super().get_context(context) return { - **super().get_context(context), - 'interface': getattr(obj, self.interface_attr), + **ctx, + 'interface': getattr(ctx['object'], self.interface_attr), }