Closes #18045: Enable adding a new MAC to an interface via quick add

This commit is contained in:
Jeremy Stretch 2024-12-10 15:36:59 -05:00
parent 39ca3ce571
commit 790aed2688
6 changed files with 41 additions and 17 deletions

View File

@ -3,9 +3,7 @@ from django.utils.translation import gettext_lazy as _
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',
@ -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)

View File

@ -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,

View File

@ -93,6 +93,7 @@ class DynamicModelChoiceMixin:
context=None,
selector=False,
quick_add=False,
quick_add_params=None,
**kwargs
):
self.model = queryset.model
@ -103,6 +104,7 @@ class DynamicModelChoiceMixin:
self.context = context or {}
self.selector = selector
self.quick_add = quick_add
self.quick_add_params = quick_add_params or {}
super().__init__(queryset, **kwargs)
@ -125,12 +127,6 @@ class DynamicModelChoiceMixin:
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):
@ -171,6 +167,19 @@ class DynamicModelChoiceMixin:
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

View File

@ -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)

View File

@ -15,7 +15,7 @@
<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"
@ -23,7 +23,7 @@
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>

View File

@ -5,7 +5,7 @@ from django.utils.translation import gettext_lazy as _
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
@ -298,6 +298,13 @@ class VMComponentForm(NetBoxModelForm):
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,