diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index dc79e40f0..fe08822a5 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -10,7 +10,7 @@ from netaddr import EUI from netaddr.core import AddrFormatError from timezone_field import TimeZoneFormField -from circuits.models import Circuit, Provider +from circuits.models import Circuit, CircuitTermination, Provider from extras.forms import ( AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldModelCSVForm, CustomFieldFilterForm, CustomFieldModelForm, LocalConfigContextFilterForm, @@ -3398,12 +3398,7 @@ class ConnectCableToDeviceForm(BootstrapMixin, forms.ModelForm): query_params={ 'site_id': '$termination_b_site', 'rack_id': '$termination_b_rack', - }, - widget=APISelect( - filter_for={ - 'termination_b_id': 'device_id', - } - ) + } ) class Meta: @@ -3418,76 +3413,106 @@ class ConnectCableToDeviceForm(BootstrapMixin, forms.ModelForm): 'length_unit': StaticSelect2, } + def clean_termination_b_id(self): + # Return the PK rather than the object + return getattr(self.cleaned_data['termination_b_id'], 'pk', None) + class ConnectCableToConsolePortForm(ConnectCableToDeviceForm): - termination_b_id = forms.IntegerField( + termination_b_id = DynamicModelChoiceField( + queryset=ConsolePort.objects.all(), label='Name', + query_params={ + 'device_id': '$termination_b_device' + }, widget=APISelect( - api_url='/api/dcim/console-ports/', disabled_indicator='cable', + full=True ) ) class ConnectCableToConsoleServerPortForm(ConnectCableToDeviceForm): - termination_b_id = forms.IntegerField( + termination_b_id = DynamicModelChoiceField( + queryset=ConsoleServerPort.objects.all(), label='Name', + query_params={ + 'device_id': '$termination_b_device' + }, widget=APISelect( - api_url='/api/dcim/console-server-ports/', disabled_indicator='cable', + full=True ) ) class ConnectCableToPowerPortForm(ConnectCableToDeviceForm): - termination_b_id = forms.IntegerField( + termination_b_id = DynamicModelChoiceField( + queryset=PowerPort.objects.all(), label='Name', + query_params={ + 'device_id': '$termination_b_device' + }, widget=APISelect( - api_url='/api/dcim/power-ports/', disabled_indicator='cable', + full=True ) ) class ConnectCableToPowerOutletForm(ConnectCableToDeviceForm): - termination_b_id = forms.IntegerField( + termination_b_id = DynamicModelChoiceField( + queryset=PowerOutlet.objects.all(), label='Name', + query_params={ + 'device_id': '$termination_b_device' + }, widget=APISelect( - api_url='/api/dcim/power-outlets/', disabled_indicator='cable', + full=True ) ) class ConnectCableToInterfaceForm(ConnectCableToDeviceForm): - termination_b_id = forms.IntegerField( + termination_b_id = DynamicModelChoiceField( + queryset=Interface.objects.all(), label='Name', + query_params={ + 'device_id': '$termination_b_device', + 'kind': 'physical', + }, widget=APISelect( - api_url='/api/dcim/interfaces/', disabled_indicator='cable', - additional_query_params={ - 'kind': 'physical', - } + full=True ) ) class ConnectCableToFrontPortForm(ConnectCableToDeviceForm): - termination_b_id = forms.IntegerField( + termination_b_id = DynamicModelChoiceField( + queryset=FrontPort.objects.all(), label='Name', + query_params={ + 'device_id': '$termination_b_device' + }, widget=APISelect( - api_url='/api/dcim/front-ports/', disabled_indicator='cable', + full=True ) ) class ConnectCableToRearPortForm(ConnectCableToDeviceForm): - termination_b_id = forms.IntegerField( + termination_b_id = DynamicModelChoiceField( + queryset=RearPort.objects.all(), label='Name', + query_params={ + 'device_id': '$termination_b_device' + }, widget=APISelect( - api_url='/api/dcim/rear-ports/', disabled_indicator='cable', + full=True ) ) @@ -3510,19 +3535,17 @@ class ConnectCableToCircuitTerminationForm(BootstrapMixin, forms.ModelForm): query_params={ 'provider_id': '$termination_b_provider', 'site_id': '$termination_b_site', + } + ) + termination_b_id = DynamicModelChoiceField( + queryset=CircuitTermination.objects.all(), + label='Side', + display_field='term_side', + query_params={ + 'circuit_id': '$termination_b_circuit' }, widget=APISelect( - filter_for={ - 'termination_b_id': 'circuit_id', - } - ) - ) - termination_b_id = forms.IntegerField( - label='Side', - widget=APISelect( - api_url='/api/circuits/circuit-terminations/', disabled_indicator='cable', - display_field='term_side', full=True ) ) @@ -3534,6 +3557,10 @@ class ConnectCableToCircuitTerminationForm(BootstrapMixin, forms.ModelForm): 'status', 'label', 'color', 'length', 'length_unit', ] + def clean_termination_b_id(self): + # Return the PK rather than the object + return getattr(self.cleaned_data['termination_b_id'], 'pk', None) + class ConnectCableToPowerFeedForm(BootstrapMixin, forms.ModelForm): termination_b_site = DynamicModelChoiceField( @@ -3558,17 +3585,17 @@ class ConnectCableToPowerFeedForm(BootstrapMixin, forms.ModelForm): query_params={ 'site_id': '$termination_b_site', 'rack_group_id': '$termination_b_rackgroup', + } + ) + termination_b_id = DynamicModelChoiceField( + queryset=PowerFeed.objects.all(), + label='Name', + query_params={ + 'power_panel_id': '$termination_b_powerpanel' }, widget=APISelect( - filter_for={ - 'termination_b_id': 'power_panel_id', - } - ) - ) - termination_b_id = forms.IntegerField( - label='Name', - widget=APISelect( - api_url='/api/dcim/power-feeds/', + disabled_indicator='cable', + full=True ) ) @@ -3579,6 +3606,10 @@ class ConnectCableToPowerFeedForm(BootstrapMixin, forms.ModelForm): 'color', 'length', 'length_unit', ] + def clean_termination_b_id(self): + # Return the PK rather than the object + return getattr(self.cleaned_data['termination_b_id'], 'pk', None) + class CableForm(BootstrapMixin, forms.ModelForm): tags = DynamicModelMultipleChoiceField( diff --git a/netbox/ipam/forms.py b/netbox/ipam/forms.py index cc83568b1..2e1917b2e 100644 --- a/netbox/ipam/forms.py +++ b/netbox/ipam/forms.py @@ -1,5 +1,4 @@ from django import forms -from django.contrib.contenttypes.models import ContentType from django.core.validators import MaxValueValidator, MinValueValidator from dcim.models import Device, Interface, Rack, Region, Site @@ -10,10 +9,9 @@ from extras.models import Tag from tenancy.forms import TenancyFilterForm, TenancyForm from tenancy.models import Tenant from utilities.forms import ( - add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditNullBooleanSelect, CSVChoiceField, - CSVModelChoiceField, CSVModelForm, DatePicker, DynamicModelChoiceField, DynamicModelMultipleChoiceField, - ExpandableIPAddressField, ReturnURLForm, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, - BOOLEAN_WITH_BLANK_CHOICES, + add_blank_choice, BootstrapMixin, BulkEditNullBooleanSelect, CSVChoiceField, CSVModelChoiceField, CSVModelForm, + DatePicker, DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableIPAddressField, ReturnURLForm, + SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, ) from virtualization.models import VirtualMachine, VMInterface from .choices import * diff --git a/netbox/tenancy/forms.py b/netbox/tenancy/forms.py index 5a420f016..142333bff 100644 --- a/netbox/tenancy/forms.py +++ b/netbox/tenancy/forms.py @@ -5,8 +5,8 @@ from extras.forms import ( ) from extras.models import Tag from utilities.forms import ( - APISelect, APISelectMultiple, BootstrapMixin, CommentField, CSVModelChoiceField, CSVModelForm, - DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField, TagFilterField, + BootstrapMixin, CommentField, CSVModelChoiceField, CSVModelForm, DynamicModelChoiceField, + DynamicModelMultipleChoiceField, SlugField, TagFilterField, ) from .models import Tenant, TenantGroup