diff --git a/netbox/dcim/forms/connections.py b/netbox/dcim/forms/connections.py index 333ac1ba6..90a3d6ce0 100644 --- a/netbox/dcim/forms/connections.py +++ b/netbox/dcim/forms/connections.py @@ -109,7 +109,7 @@ def get_cable_form(a_type, b_type): super().clean() # Set the A/B terminations on the Cable instance - self.instance.a_terminations = self.cleaned_data['a_terminations'] - self.instance.b_terminations = self.cleaned_data['b_terminations'] + self.instance.a_terminations = self.cleaned_data.get('a_terminations', []) + self.instance.b_terminations = self.cleaned_data.get('b_terminations', []) return _CableForm diff --git a/netbox/dcim/forms/model_forms.py b/netbox/dcim/forms/model_forms.py index b25c43b12..cc7100e3c 100644 --- a/netbox/dcim/forms/model_forms.py +++ b/netbox/dcim/forms/model_forms.py @@ -13,8 +13,7 @@ from netbox.forms import NetBoxModelForm from tenancy.forms import TenancyForm from utilities.forms import BootstrapMixin, add_blank_choice from utilities.forms.fields import ( - CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, - NumericArrayField, SlugField, + CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, NumericArrayField, SlugField, ) from utilities.forms.widgets import APISelect, ClearableFileInput, HTMXSelect, NumberWithOptions, SelectWithPK from virtualization.models import Cluster @@ -617,13 +616,10 @@ class ModuleForm(ModuleCommonForm, NetBoxModelForm): def get_termination_type_choices(): - return [ - (None, '---------'), - *[ - (f'{ct.app_label}.{ct.model}', ct.model_class()._meta.verbose_name.title()) - for ct in ContentType.objects.filter(CABLE_TERMINATION_MODELS) - ] - ] + return add_blank_choice([ + (f'{ct.app_label}.{ct.model}', ct.model_class()._meta.verbose_name.title()) + for ct in ContentType.objects.filter(CABLE_TERMINATION_MODELS) + ]) class CableForm(TenancyForm, NetBoxModelForm): diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 320e52680..a2e9ef12a 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -3201,18 +3201,17 @@ class CableEditView(generic.ObjectEditView): Hack into get_object() to set the form class when editing an existing Cable, since ObjectEditView doesn't currently provide a hook for dynamic class resolution. """ - a_terminations_type = request.GET.get('a_terminations_type') - b_terminations_type = request.GET.get('b_terminations_type') + a_terminations_type = request.POST.get('a_terminations_type') or request.GET.get('a_terminations_type') + b_terminations_type = request.POST.get('b_terminations_type') or request.GET.get('b_terminations_type') if obj.pk: - # TODO: Optimize this logic - termination_a = obj.terminations.filter(cable_end='A').first() - a_type = termination_a.termination._meta.model if termination_a else ( - CABLE_TERMINATION_TYPES.get(a_terminations_type) - ) - termination_b = obj.terminations.filter(cable_end='B').first() - b_type = termination_b.termination._meta.model if termination_b else ( - CABLE_TERMINATION_TYPES.get(b_terminations_type) - ) + if not a_terminations_type and (termination_a := obj.terminations.filter(cable_end='A').first()): + a_type = termination_a.termination._meta.model + else: + a_type = CABLE_TERMINATION_TYPES.get(a_terminations_type) + if not b_terminations_type and (termination_b := obj.terminations.filter(cable_end='B').first()): + b_type = termination_b.termination._meta.model + else: + b_type = CABLE_TERMINATION_TYPES.get(b_terminations_type) self.form = forms.get_cable_form(a_type, b_type)