Skip to content

Commit

Permalink
Closes #18045: Enable adding a new MAC to an interface via quick add
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremystretch committed Dec 10, 2024
1 parent ce365da commit 3ce6f90
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 17 deletions.
8 changes: 0 additions & 8 deletions netbox/dcim/forms/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@

from dcim.choices import *
from dcim.constants import *
from dcim.models import MACAddress
from utilities.forms import get_field_value
from utilities.forms.fields import DynamicModelChoiceField

__all__ = (
'InterfaceCommonForm',
Expand All @@ -20,12 +18,6 @@ class InterfaceCommonForm(forms.Form):
max_value=INTERFACE_MTU_MAX,
label=_('MTU')
)
primary_mac_address = DynamicModelChoiceField(
queryset=MACAddress.objects.all(),
label=_('Primary MAC address'),
required=False,
quick_add=True
)

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand Down
7 changes: 7 additions & 0 deletions netbox/dcim/forms/model_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -1410,6 +1410,13 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
required=False,
label=_('VRF')
)
primary_mac_address = DynamicModelChoiceField(
queryset=MACAddress.objects.all(),
label=_('Primary MAC address'),
required=False,
quick_add=True,
quick_add_params={'interface': '$pk'}
)
wwn = forms.CharField(
empty_value=None,
required=False,
Expand Down
21 changes: 15 additions & 6 deletions netbox/utilities/forms/fields/dynamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def __init__(
context=None,
selector=False,
quick_add=False,
quick_add_params=None,
**kwargs
):
self.model = queryset.model
Expand All @@ -103,6 +104,7 @@ def __init__(
self.context = context or {}
self.selector = selector
self.quick_add = quick_add
self.quick_add_params = quick_add_params or {}

super().__init__(queryset, **kwargs)

Expand All @@ -125,12 +127,6 @@ def widget_attrs(self, widget):
if self.selector:
attrs['selector'] = self.model._meta.label_lower

# Include quick add?
if self.quick_add:
app_label = self.model._meta.app_label
model_name = self.model._meta.model_name
attrs['quick_add'] = reverse_lazy(f'{app_label}:{model_name}_add')

return attrs

def get_bound_field(self, form, field_name):
Expand Down Expand Up @@ -171,6 +167,19 @@ def get_bound_field(self, form, field_name):
viewname = get_viewname(self.queryset.model, action='list', rest_api=True)
widget.attrs['data-url'] = reverse(viewname)

# Include quick add?
if self.quick_add:
app_label = self.model._meta.app_label
model_name = self.model._meta.model_name
widget.quick_add_context = {
'url': reverse_lazy(f'{app_label}:{model_name}_add'),
'params': {},
}
for k, v in self.quick_add_params.items():
if v == '$pk':
v = form.instance.pk
widget.quick_add_context['params'][k] = v

return bound_field


Expand Down
9 changes: 9 additions & 0 deletions netbox/utilities/forms/widgets/apiselect.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ class APISelect(forms.Select):
dynamic_params: Dict[str, str]
static_params: Dict[str, List[str]]

def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)

# Add quick-add context data, if set on the widget
if hasattr(self, 'quick_add_context'):
context['quick_add'] = self.quick_add_context

return context

def __init__(self, api_url=None, full=False, *args, **kwargs):
super().__init__(*args, **kwargs)

Expand Down
4 changes: 2 additions & 2 deletions netbox/utilities/templates/widgets/apiselect.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
<i class="mdi mdi-database-search-outline"></i>
</button>
{% endif %}
{% if widget.attrs.quick_add and not widget.attrs.disabled %}
{% if quick_add and not widget.attrs.disabled %}
{# Opens the quick add modal #}
<button
type="button"
title="{% trans "Quick add" %}"
class="btn btn-outline-secondary ms-1"
data-bs-toggle="modal"
data-bs-target="#htmx-modal"
hx-get="{{ widget.attrs.quick_add }}?_quickadd=True&target={{ widget.attrs.id }}"
hx-get="{{ quick_add.url }}?_quickadd=True&target={{ widget.attrs.id }}{% for k, v in quick_add.params.items %}&{{ k }}={{ v }}{% endfor %}"
hx-target="#htmx-modal-content"
>
<i class="mdi mdi-plus-circle"></i>
Expand Down
9 changes: 8 additions & 1 deletion netbox/virtualization/forms/model_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from dcim.forms.common import InterfaceCommonForm
from dcim.forms.mixins import ScopedForm
from dcim.models import Device, DeviceRole, Platform, Rack, Region, Site, SiteGroup
from dcim.models import Device, DeviceRole, MACAddress, Platform, Rack, Region, Site, SiteGroup
from extras.models import ConfigTemplate
from ipam.choices import VLANQinQRoleChoices
from ipam.models import IPAddress, VLAN, VLANGroup, VLANTranslationPolicy, VRF
Expand Down Expand Up @@ -298,6 +298,13 @@ def __init__(self, *args, **kwargs):


class VMInterfaceForm(InterfaceCommonForm, VMComponentForm):
primary_mac_address = DynamicModelChoiceField(
queryset=MACAddress.objects.all(),
label=_('Primary MAC address'),
required=False,
quick_add=True,
quick_add_params={'vminterface': '$pk'}
)
parent = DynamicModelChoiceField(
queryset=VMInterface.objects.all(),
required=False,
Expand Down

0 comments on commit 3ce6f90

Please sign in to comment.