mirror of
https://github.com/netbox-community/netbox.git
synced 2026-04-10 03:13:48 +02:00
Merge branch 'develop' into feature
This commit is contained in:
@@ -916,6 +916,7 @@ class InterfaceTypeChoices(ChoiceSet):
|
||||
TYPE_80211AD = 'ieee802.11ad'
|
||||
TYPE_80211AX = 'ieee802.11ax'
|
||||
TYPE_80211AY = 'ieee802.11ay'
|
||||
TYPE_80211BE = 'ieee802.11be'
|
||||
TYPE_802151 = 'ieee802.15.1'
|
||||
TYPE_OTHER_WIRELESS = 'other-wireless'
|
||||
|
||||
@@ -1087,6 +1088,7 @@ class InterfaceTypeChoices(ChoiceSet):
|
||||
(TYPE_80211AD, 'IEEE 802.11ad'),
|
||||
(TYPE_80211AX, 'IEEE 802.11ax'),
|
||||
(TYPE_80211AY, 'IEEE 802.11ay'),
|
||||
(TYPE_80211BE, 'IEEE 802.11be'),
|
||||
(TYPE_802151, 'IEEE 802.15.1 (Bluetooth)'),
|
||||
(TYPE_OTHER_WIRELESS, 'Other (Wireless)'),
|
||||
)
|
||||
|
||||
@@ -49,6 +49,7 @@ WIRELESS_IFACE_TYPES = [
|
||||
InterfaceTypeChoices.TYPE_80211AD,
|
||||
InterfaceTypeChoices.TYPE_80211AX,
|
||||
InterfaceTypeChoices.TYPE_80211AY,
|
||||
InterfaceTypeChoices.TYPE_80211BE,
|
||||
InterfaceTypeChoices.TYPE_802151,
|
||||
InterfaceTypeChoices.TYPE_OTHER_WIRELESS,
|
||||
]
|
||||
|
||||
@@ -1295,12 +1295,17 @@ class ComponentBulkEditForm(NetBoxModelBulkEditForm):
|
||||
required=False
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
def __init__(self, *args, initial=None, **kwargs):
|
||||
try:
|
||||
self.device_id = int(initial.get('device'))
|
||||
except (TypeError, ValueError):
|
||||
self.device_id = None
|
||||
|
||||
super().__init__(*args, initial=initial, **kwargs)
|
||||
|
||||
# Limit module queryset to Modules which belong to the parent Device
|
||||
if 'device' in self.initial:
|
||||
device = Device.objects.filter(pk=self.initial['device']).first()
|
||||
if self.device_id:
|
||||
device = Device.objects.filter(pk=self.device_id).first()
|
||||
self.fields['module'].queryset = Module.objects.filter(device=device)
|
||||
else:
|
||||
self.fields['module'].choices = ()
|
||||
@@ -1308,8 +1313,8 @@ class ComponentBulkEditForm(NetBoxModelBulkEditForm):
|
||||
|
||||
|
||||
class ConsolePortBulkEditForm(
|
||||
form_from_model(ConsolePort, ['label', 'type', 'speed', 'mark_connected', 'description']),
|
||||
ComponentBulkEditForm
|
||||
ComponentBulkEditForm,
|
||||
form_from_model(ConsolePort, ['label', 'type', 'speed', 'mark_connected', 'description'])
|
||||
):
|
||||
mark_connected = forms.NullBooleanField(
|
||||
label=_('Mark connected'),
|
||||
@@ -1325,8 +1330,8 @@ class ConsolePortBulkEditForm(
|
||||
|
||||
|
||||
class ConsoleServerPortBulkEditForm(
|
||||
form_from_model(ConsoleServerPort, ['label', 'type', 'speed', 'mark_connected', 'description']),
|
||||
ComponentBulkEditForm
|
||||
ComponentBulkEditForm,
|
||||
form_from_model(ConsoleServerPort, ['label', 'type', 'speed', 'mark_connected', 'description'])
|
||||
):
|
||||
mark_connected = forms.NullBooleanField(
|
||||
label=_('Mark connected'),
|
||||
@@ -1342,8 +1347,8 @@ class ConsoleServerPortBulkEditForm(
|
||||
|
||||
|
||||
class PowerPortBulkEditForm(
|
||||
form_from_model(PowerPort, ['label', 'type', 'maximum_draw', 'allocated_draw', 'mark_connected', 'description']),
|
||||
ComponentBulkEditForm
|
||||
ComponentBulkEditForm,
|
||||
form_from_model(PowerPort, ['label', 'type', 'maximum_draw', 'allocated_draw', 'mark_connected', 'description'])
|
||||
):
|
||||
mark_connected = forms.NullBooleanField(
|
||||
label=_('Mark connected'),
|
||||
@@ -1360,8 +1365,8 @@ class PowerPortBulkEditForm(
|
||||
|
||||
|
||||
class PowerOutletBulkEditForm(
|
||||
form_from_model(PowerOutlet, ['label', 'type', 'feed_leg', 'power_port', 'mark_connected', 'description']),
|
||||
ComponentBulkEditForm
|
||||
ComponentBulkEditForm,
|
||||
form_from_model(PowerOutlet, ['label', 'type', 'feed_leg', 'power_port', 'mark_connected', 'description'])
|
||||
):
|
||||
mark_connected = forms.NullBooleanField(
|
||||
label=_('Mark connected'),
|
||||
@@ -1380,8 +1385,8 @@ class PowerOutletBulkEditForm(
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# Limit power_port queryset to PowerPorts which belong to the parent Device
|
||||
if 'device' in self.initial:
|
||||
device = Device.objects.filter(pk=self.initial['device']).first()
|
||||
if self.device_id:
|
||||
device = Device.objects.filter(pk=self.device_id).first()
|
||||
self.fields['power_port'].queryset = PowerPort.objects.filter(device=device)
|
||||
else:
|
||||
self.fields['power_port'].choices = ()
|
||||
@@ -1389,12 +1394,12 @@ class PowerOutletBulkEditForm(
|
||||
|
||||
|
||||
class InterfaceBulkEditForm(
|
||||
ComponentBulkEditForm,
|
||||
form_from_model(Interface, [
|
||||
'label', 'type', 'parent', 'bridge', 'lag', 'speed', 'duplex', 'mac_address', 'wwn', 'mtu', 'mgmt_only',
|
||||
'mark_connected', 'description', 'mode', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width',
|
||||
'tx_power', 'wireless_lans'
|
||||
]),
|
||||
ComponentBulkEditForm
|
||||
])
|
||||
):
|
||||
enabled = forms.NullBooleanField(
|
||||
label=_('Enabled'),
|
||||
@@ -1523,8 +1528,8 @@ class InterfaceBulkEditForm(
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
if 'device' in self.initial:
|
||||
device = Device.objects.filter(pk=self.initial['device']).first()
|
||||
if self.device_id:
|
||||
device = Device.objects.filter(pk=self.device_id).first()
|
||||
|
||||
# Restrict parent/bridge/LAG interface assignment by device
|
||||
self.fields['parent'].widget.add_query_param('virtual_chassis_member_id', device.pk)
|
||||
@@ -1587,8 +1592,8 @@ class InterfaceBulkEditForm(
|
||||
|
||||
|
||||
class FrontPortBulkEditForm(
|
||||
form_from_model(FrontPort, ['label', 'type', 'color', 'mark_connected', 'description']),
|
||||
ComponentBulkEditForm
|
||||
ComponentBulkEditForm,
|
||||
form_from_model(FrontPort, ['label', 'type', 'color', 'mark_connected', 'description'])
|
||||
):
|
||||
mark_connected = forms.NullBooleanField(
|
||||
label=_('Mark connected'),
|
||||
@@ -1604,8 +1609,8 @@ class FrontPortBulkEditForm(
|
||||
|
||||
|
||||
class RearPortBulkEditForm(
|
||||
form_from_model(RearPort, ['label', 'type', 'color', 'mark_connected', 'description']),
|
||||
ComponentBulkEditForm
|
||||
ComponentBulkEditForm,
|
||||
form_from_model(RearPort, ['label', 'type', 'color', 'mark_connected', 'description'])
|
||||
):
|
||||
mark_connected = forms.NullBooleanField(
|
||||
label=_('Mark connected'),
|
||||
|
||||
@@ -19,7 +19,7 @@ def get_cable_form(a_type, b_type):
|
||||
# Device component
|
||||
if hasattr(term_cls, 'device'):
|
||||
|
||||
attrs[f'termination_{cable_end}_device'] = DynamicModelChoiceField(
|
||||
attrs[f'termination_{cable_end}_device'] = DynamicModelMultipleChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
label=_('Device'),
|
||||
required=False,
|
||||
@@ -33,6 +33,7 @@ def get_cable_form(a_type, b_type):
|
||||
label=term_cls._meta.verbose_name.title(),
|
||||
context={
|
||||
'disabled': '_occupied',
|
||||
'parent': 'device',
|
||||
},
|
||||
query_params={
|
||||
'device_id': f'$termination_{cable_end}_device',
|
||||
@@ -43,7 +44,7 @@ def get_cable_form(a_type, b_type):
|
||||
# PowerFeed
|
||||
elif term_cls == PowerFeed:
|
||||
|
||||
attrs[f'termination_{cable_end}_powerpanel'] = DynamicModelChoiceField(
|
||||
attrs[f'termination_{cable_end}_powerpanel'] = DynamicModelMultipleChoiceField(
|
||||
queryset=PowerPanel.objects.all(),
|
||||
label=_('Power Panel'),
|
||||
required=False,
|
||||
@@ -57,6 +58,7 @@ def get_cable_form(a_type, b_type):
|
||||
label=_('Power Feed'),
|
||||
context={
|
||||
'disabled': '_occupied',
|
||||
'parent': 'powerpanel',
|
||||
},
|
||||
query_params={
|
||||
'power_panel_id': f'$termination_{cable_end}_powerpanel',
|
||||
@@ -66,7 +68,7 @@ def get_cable_form(a_type, b_type):
|
||||
# CircuitTermination
|
||||
elif term_cls == CircuitTermination:
|
||||
|
||||
attrs[f'termination_{cable_end}_circuit'] = DynamicModelChoiceField(
|
||||
attrs[f'termination_{cable_end}_circuit'] = DynamicModelMultipleChoiceField(
|
||||
queryset=Circuit.objects.all(),
|
||||
label=_('Circuit'),
|
||||
selector=True,
|
||||
@@ -79,6 +81,7 @@ def get_cable_form(a_type, b_type):
|
||||
label=_('Side'),
|
||||
context={
|
||||
'disabled': '_occupied',
|
||||
'parent': 'circuit',
|
||||
},
|
||||
query_params={
|
||||
'circuit_id': f'$termination_{cable_end}_circuit',
|
||||
|
||||
@@ -2126,7 +2126,7 @@ class DeviceRenderConfigView(generic.ObjectView):
|
||||
try:
|
||||
rendered_config = config_template.render(context=context_data)
|
||||
except TemplateError as e:
|
||||
messages.error(request, f"An error occurred while rendering the template: {e}")
|
||||
messages.error(request, _("An error occurred while rendering the template: {error}").format(error=e))
|
||||
rendered_config = traceback.format_exc()
|
||||
|
||||
return {
|
||||
@@ -2890,7 +2890,13 @@ class DeviceBayPopulateView(generic.ObjectEditView):
|
||||
device_bay.snapshot()
|
||||
device_bay.installed_device = form.cleaned_data['installed_device']
|
||||
device_bay.save()
|
||||
messages.success(request, "Added {} to {}.".format(device_bay.installed_device, device_bay))
|
||||
messages.success(
|
||||
request,
|
||||
_("Installed device {device} in bay {device_bay}.").format(
|
||||
device=device_bay.installed_device,
|
||||
device_bay=device_bay
|
||||
)
|
||||
)
|
||||
return_url = self.get_return_url(request)
|
||||
|
||||
return redirect(return_url)
|
||||
@@ -2925,7 +2931,13 @@ class DeviceBayDepopulateView(generic.ObjectEditView):
|
||||
removed_device = device_bay.installed_device
|
||||
device_bay.installed_device = None
|
||||
device_bay.save()
|
||||
messages.success(request, f"{removed_device} has been removed from {device_bay}.")
|
||||
messages.success(
|
||||
request,
|
||||
_("Removed device {device} from bay {device_bay}.").format(
|
||||
device=removed_device,
|
||||
device_bay=device_bay
|
||||
)
|
||||
)
|
||||
return_url = self.get_return_url(request, device_bay.device)
|
||||
|
||||
return redirect(return_url)
|
||||
@@ -3493,7 +3505,7 @@ class VirtualChassisAddMemberView(ObjectPermissionRequiredMixin, GetReturnURLMix
|
||||
|
||||
membership_form.save()
|
||||
messages.success(request, mark_safe(
|
||||
f'Added member <a href="{device.get_absolute_url()}">{escape(device)}</a>'
|
||||
_('Added member <a href="{url}">{escape(device)}</a>').format(url=device.get_absolute_url())
|
||||
))
|
||||
|
||||
if '_addanother' in request.POST:
|
||||
@@ -3538,7 +3550,10 @@ class VirtualChassisRemoveMemberView(ObjectPermissionRequiredMixin, GetReturnURL
|
||||
# Protect master device from being removed
|
||||
virtual_chassis = VirtualChassis.objects.filter(master=device).first()
|
||||
if virtual_chassis is not None:
|
||||
messages.error(request, f'Unable to remove master device {device} from the virtual chassis.')
|
||||
messages.error(
|
||||
request,
|
||||
_('Unable to remove master device {device} from the virtual chassis.').format(device=device)
|
||||
)
|
||||
return redirect(device.get_absolute_url())
|
||||
|
||||
if form.is_valid():
|
||||
@@ -3550,7 +3565,10 @@ class VirtualChassisRemoveMemberView(ObjectPermissionRequiredMixin, GetReturnURL
|
||||
device.vc_priority = None
|
||||
device.save()
|
||||
|
||||
msg = 'Removed {} from virtual chassis {}'.format(device, device.virtual_chassis)
|
||||
msg = _('Removed {device} from virtual chassis {chassis}').format(
|
||||
device=device,
|
||||
chassis=device.virtual_chassis
|
||||
)
|
||||
messages.success(request, msg)
|
||||
|
||||
return redirect(self.get_return_url(request, device))
|
||||
|
||||
Reference in New Issue
Block a user