|
@@ -445,7 +445,7 @@ class PlatformForm(BootstrapMixin, forms.ModelForm):
|
|
|
|
|
|
class DeviceForm(BootstrapMixin, CustomFieldForm):
|
|
|
site = forms.ModelChoiceField(queryset=Site.objects.all(), widget=forms.Select(attrs={'filter-for': 'rack'}))
|
|
|
- rack = forms.ModelChoiceField(queryset=Rack.objects.all(), widget=APISelect(
|
|
|
+ rack = forms.ModelChoiceField(queryset=Rack.objects.all(), required=False, widget=APISelect(
|
|
|
api_url='/api/dcim/racks/?site_id={{site}}',
|
|
|
display_field='display_name',
|
|
|
attrs={'filter-for': 'position'}
|
|
@@ -549,7 +549,7 @@ class DeviceForm(BootstrapMixin, CustomFieldForm):
|
|
|
if pk and self.instance.device_type.is_child_device and hasattr(self.instance, 'parent_bay'):
|
|
|
self.fields['site'].disabled = True
|
|
|
self.fields['rack'].disabled = True
|
|
|
- self.initial['site'] = self.instance.parent_bay.device.rack.site_id
|
|
|
+ self.initial['site'] = self.instance.parent_bay.device.site_id
|
|
|
self.initial['rack'] = self.instance.parent_bay.device.rack_id
|
|
|
|
|
|
|
|
@@ -585,7 +585,7 @@ class DeviceFromCSVForm(BaseDeviceFromCSVForm):
|
|
|
site = forms.ModelChoiceField(queryset=Site.objects.all(), to_field_name='name', error_messages={
|
|
|
'invalid_choice': 'Invalid site name.',
|
|
|
})
|
|
|
- rack_name = forms.CharField()
|
|
|
+ rack_name = forms.CharField(required=False)
|
|
|
face = forms.CharField(required=False)
|
|
|
|
|
|
class Meta(BaseDeviceFromCSVForm.Meta):
|
|
@@ -748,9 +748,13 @@ class ConsolePortCreateForm(BootstrapMixin, forms.Form):
|
|
|
|
|
|
|
|
|
class ConsoleConnectionCSVForm(forms.Form):
|
|
|
- console_server = FlexibleModelChoiceField(queryset=Device.objects.filter(device_type__is_console_server=True),
|
|
|
- to_field_name='name',
|
|
|
- error_messages={'invalid_choice': 'Console server not found'})
|
|
|
+ console_server = FlexibleModelChoiceField(
|
|
|
+ queryset=Device.objects.filter(device_type__is_console_server=True),
|
|
|
+ to_field_name='name',
|
|
|
+ error_messages={
|
|
|
+ 'invalid_choice': 'Console server not found',
|
|
|
+ }
|
|
|
+ )
|
|
|
cs_port = forms.CharField()
|
|
|
device = FlexibleModelChoiceField(queryset=Device.objects.all(), to_field_name='name',
|
|
|
error_messages={'invalid_choice': 'Device not found'})
|
|
@@ -815,22 +819,49 @@ class ConsoleConnectionImportForm(BootstrapMixin, BulkImportForm):
|
|
|
|
|
|
|
|
|
class ConsolePortConnectionForm(BootstrapMixin, forms.ModelForm):
|
|
|
- rack = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False,
|
|
|
- widget=forms.Select(attrs={'filter-for': 'console_server'}))
|
|
|
- console_server = forms.ModelChoiceField(queryset=Device.objects.all(), label='Console Server', required=False,
|
|
|
- widget=APISelect(api_url='/api/dcim/devices/?rack_id={{rack}}&is_console_server=True',
|
|
|
- display_field='display_name',
|
|
|
- attrs={'filter-for': 'cs_port'}))
|
|
|
- livesearch = forms.CharField(required=False, label='Console Server', widget=Livesearch(
|
|
|
- query_key='q', query_url='dcim-api:device_list', field_to_update='console_server')
|
|
|
+ site = forms.ModelChoiceField(
|
|
|
+ queryset=Site.objects.all(),
|
|
|
+ widget=forms.HiddenInput(),
|
|
|
+ )
|
|
|
+ rack = forms.ModelChoiceField(
|
|
|
+ queryset=Rack.objects.all(),
|
|
|
+ label='Rack',
|
|
|
+ required=False,
|
|
|
+ widget=forms.Select(
|
|
|
+ attrs={'filter-for': 'console_server', 'nullable': 'true'}
|
|
|
+ )
|
|
|
+ )
|
|
|
+ console_server = forms.ModelChoiceField(
|
|
|
+ queryset=Device.objects.all(),
|
|
|
+ label='Console Server',
|
|
|
+ required=False,
|
|
|
+ widget=APISelect(
|
|
|
+ api_url='/api/dcim/devices/?site_id={{site}}&rack_id={{rack}}&is_console_server=True',
|
|
|
+ display_field='display_name',
|
|
|
+ attrs={'filter-for': 'cs_port'}
|
|
|
+ )
|
|
|
+ )
|
|
|
+ livesearch = forms.CharField(
|
|
|
+ required=False,
|
|
|
+ label='Console Server',
|
|
|
+ widget=Livesearch(
|
|
|
+ query_key='q',
|
|
|
+ query_url='dcim-api:device_list',
|
|
|
+ field_to_update='console_server',
|
|
|
+ )
|
|
|
+ )
|
|
|
+ cs_port = forms.ModelChoiceField(
|
|
|
+ queryset=ConsoleServerPort.objects.all(),
|
|
|
+ label='Port',
|
|
|
+ widget=APISelect(
|
|
|
+ api_url='/api/dcim/devices/{{console_server}}/console-server-ports/',
|
|
|
+ disabled_indicator='connected_console',
|
|
|
+ )
|
|
|
)
|
|
|
- cs_port = forms.ModelChoiceField(queryset=ConsoleServerPort.objects.all(), label='Port',
|
|
|
- widget=APISelect(api_url='/api/dcim/devices/{{console_server}}/console-server-ports/',
|
|
|
- disabled_indicator='connected_console'))
|
|
|
|
|
|
class Meta:
|
|
|
model = ConsolePort
|
|
|
- fields = ['rack', 'console_server', 'livesearch', 'cs_port', 'connection_status']
|
|
|
+ fields = ['site', 'rack', 'console_server', 'livesearch', 'cs_port', 'connection_status']
|
|
|
labels = {
|
|
|
'cs_port': 'Port',
|
|
|
'connection_status': 'Status',
|
|
@@ -843,17 +874,22 @@ class ConsolePortConnectionForm(BootstrapMixin, forms.ModelForm):
|
|
|
if not self.instance.pk:
|
|
|
raise RuntimeError("ConsolePortConnectionForm must be initialized with an existing ConsolePort instance.")
|
|
|
|
|
|
- self.fields['rack'].queryset = Rack.objects.filter(site=self.instance.device.rack.site)
|
|
|
+ self.initial['site'] = self.instance.device.site
|
|
|
+ self.fields['rack'].queryset = Rack.objects.filter(site=self.instance.device.site)
|
|
|
self.fields['cs_port'].required = True
|
|
|
self.fields['connection_status'].choices = CONNECTION_STATUS_CHOICES
|
|
|
|
|
|
# Initialize console server choices
|
|
|
if self.is_bound and self.data.get('rack'):
|
|
|
- self.fields['console_server'].queryset = Device.objects.filter(rack=self.data['rack'], device_type__is_console_server=True)
|
|
|
+ self.fields['console_server'].queryset = Device.objects.filter(rack=self.data['rack'],
|
|
|
+ device_type__is_console_server=True)
|
|
|
elif self.initial.get('rack'):
|
|
|
- self.fields['console_server'].queryset = Device.objects.filter(rack=self.initial['rack'], device_type__is_console_server=True)
|
|
|
+ self.fields['console_server'].queryset = Device.objects.filter(rack=self.initial['rack'],
|
|
|
+ device_type__is_console_server=True)
|
|
|
else:
|
|
|
- self.fields['console_server'].choices = []
|
|
|
+ self.fields['console_server'].queryset = Device.objects.filter(site=self.instance.device.site,
|
|
|
+ rack__isnull=True,
|
|
|
+ device_type__is_console_server=True)
|
|
|
|
|
|
# Initialize CS port choices
|
|
|
if self.is_bound:
|
|
@@ -883,22 +919,56 @@ class ConsoleServerPortCreateForm(BootstrapMixin, forms.Form):
|
|
|
|
|
|
|
|
|
class ConsoleServerPortConnectionForm(BootstrapMixin, forms.Form):
|
|
|
- rack = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False,
|
|
|
- widget=forms.Select(attrs={'filter-for': 'device'}))
|
|
|
- device = forms.ModelChoiceField(queryset=Device.objects.all(), label='Device', required=False,
|
|
|
- widget=APISelect(api_url='/api/dcim/devices/?rack_id={{rack}}',
|
|
|
- display_field='display_name', attrs={'filter-for': 'port'}))
|
|
|
- livesearch = forms.CharField(required=False, label='Device', widget=Livesearch(
|
|
|
- query_key='q', query_url='dcim-api:device_list', field_to_update='device')
|
|
|
+ site = forms.ModelChoiceField(
|
|
|
+ queryset=Site.objects.all(),
|
|
|
+ widget=forms.HiddenInput(),
|
|
|
+ )
|
|
|
+ rack = forms.ModelChoiceField(
|
|
|
+ queryset=Rack.objects.all(),
|
|
|
+ label='Rack',
|
|
|
+ required=False,
|
|
|
+ widget=forms.Select(
|
|
|
+ attrs={'filter-for': 'device', 'nullable': 'true'}
|
|
|
+ )
|
|
|
+ )
|
|
|
+ device = forms.ModelChoiceField(
|
|
|
+ queryset=Device.objects.all(),
|
|
|
+ label='Device',
|
|
|
+ required=False,
|
|
|
+ widget=APISelect(
|
|
|
+ api_url='/api/dcim/devices/?site_id={{site}}&rack_id={{rack}}',
|
|
|
+ display_field='display_name',
|
|
|
+ attrs={'filter-for': 'port'}
|
|
|
+ )
|
|
|
+ )
|
|
|
+ livesearch = forms.CharField(
|
|
|
+ required=False,
|
|
|
+ label='Device',
|
|
|
+ widget=Livesearch(
|
|
|
+ query_key='q',
|
|
|
+ query_url='dcim-api:device_list',
|
|
|
+ field_to_update='device'
|
|
|
+ )
|
|
|
+ )
|
|
|
+ port = forms.ModelChoiceField(
|
|
|
+ queryset=ConsolePort.objects.all(),
|
|
|
+ label='Port',
|
|
|
+ widget=APISelect(
|
|
|
+ api_url='/api/dcim/devices/{{device}}/console-ports/',
|
|
|
+ disabled_indicator='cs_port'
|
|
|
+ )
|
|
|
+ )
|
|
|
+ connection_status = forms.BooleanField(
|
|
|
+ required=False,
|
|
|
+ initial=CONNECTION_STATUS_CONNECTED,
|
|
|
+ label='Status',
|
|
|
+ widget=forms.Select(
|
|
|
+ choices=CONNECTION_STATUS_CHOICES
|
|
|
+ )
|
|
|
)
|
|
|
- port = forms.ModelChoiceField(queryset=ConsolePort.objects.all(), label='Port',
|
|
|
- widget=APISelect(api_url='/api/dcim/devices/{{device}}/console-ports/',
|
|
|
- disabled_indicator='cs_port'))
|
|
|
- connection_status = forms.BooleanField(required=False, initial=CONNECTION_STATUS_CONNECTED, label='Status',
|
|
|
- widget=forms.Select(choices=CONNECTION_STATUS_CHOICES))
|
|
|
|
|
|
class Meta:
|
|
|
- fields = ['rack', 'device', 'livesearch', 'port', 'connection_status']
|
|
|
+ fields = ['site', 'rack', 'device', 'livesearch', 'port', 'connection_status']
|
|
|
labels = {
|
|
|
'connection_status': 'Status',
|
|
|
}
|
|
@@ -907,7 +977,8 @@ class ConsoleServerPortConnectionForm(BootstrapMixin, forms.Form):
|
|
|
|
|
|
super(ConsoleServerPortConnectionForm, self).__init__(*args, **kwargs)
|
|
|
|
|
|
- self.fields['rack'].queryset = Rack.objects.filter(site=consoleserverport.device.rack.site)
|
|
|
+ self.initial['site'] = consoleserverport.device.site
|
|
|
+ self.fields['rack'].queryset = Rack.objects.filter(site=consoleserverport.device.site)
|
|
|
|
|
|
# Initialize device choices
|
|
|
if self.is_bound and self.data.get('rack'):
|
|
@@ -915,7 +986,8 @@ class ConsoleServerPortConnectionForm(BootstrapMixin, forms.Form):
|
|
|
elif self.initial.get('rack', None):
|
|
|
self.fields['device'].queryset = Device.objects.filter(rack=self.initial['rack'])
|
|
|
else:
|
|
|
- self.fields['device'].choices = []
|
|
|
+ self.fields['device'].queryset = Device.objects.filter(site=consoleserverport.device.site,
|
|
|
+ rack__isnull=True)
|
|
|
|
|
|
# Initialize port choices
|
|
|
if self.is_bound:
|
|
@@ -945,8 +1017,13 @@ class PowerPortCreateForm(BootstrapMixin, forms.Form):
|
|
|
|
|
|
|
|
|
class PowerConnectionCSVForm(forms.Form):
|
|
|
- pdu = FlexibleModelChoiceField(queryset=Device.objects.filter(device_type__is_pdu=True), to_field_name='name',
|
|
|
- error_messages={'invalid_choice': 'PDU not found.'})
|
|
|
+ pdu = FlexibleModelChoiceField(
|
|
|
+ queryset=Device.objects.filter(device_type__is_pdu=True),
|
|
|
+ to_field_name='name',
|
|
|
+ error_messages={
|
|
|
+ 'invalid_choice': 'PDU not found.',
|
|
|
+ }
|
|
|
+ )
|
|
|
power_outlet = forms.CharField()
|
|
|
device = FlexibleModelChoiceField(queryset=Device.objects.all(), to_field_name='name',
|
|
|
error_messages={'invalid_choice': 'Device not found'})
|
|
@@ -1012,21 +1089,46 @@ class PowerConnectionImportForm(BootstrapMixin, BulkImportForm):
|
|
|
|
|
|
|
|
|
class PowerPortConnectionForm(BootstrapMixin, forms.ModelForm):
|
|
|
- rack = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False,
|
|
|
- widget=forms.Select(attrs={'filter-for': 'pdu'}))
|
|
|
- pdu = forms.ModelChoiceField(queryset=Device.objects.all(), label='PDU', required=False,
|
|
|
- widget=APISelect(api_url='/api/dcim/devices/?rack_id={{rack}}&is_pdu=True',
|
|
|
- display_field='display_name', attrs={'filter-for': 'power_outlet'}))
|
|
|
- livesearch = forms.CharField(required=False, label='PDU', widget=Livesearch(
|
|
|
- query_key='q', query_url='dcim-api:device_list', field_to_update='pdu')
|
|
|
+ site = forms.ModelChoiceField(queryset=Site.objects.all(), widget=forms.HiddenInput())
|
|
|
+ rack = forms.ModelChoiceField(
|
|
|
+ queryset=Rack.objects.all(),
|
|
|
+ label='Rack',
|
|
|
+ required=False,
|
|
|
+ widget=forms.Select(
|
|
|
+ attrs={'filter-for': 'pdu', 'nullable': 'true'}
|
|
|
+ )
|
|
|
+ )
|
|
|
+ pdu = forms.ModelChoiceField(
|
|
|
+ queryset=Device.objects.all(),
|
|
|
+ label='PDU',
|
|
|
+ required=False,
|
|
|
+ widget=APISelect(
|
|
|
+ api_url='/api/dcim/devices/?site_id={{site}}&rack_id={{rack}}&is_pdu=True',
|
|
|
+ display_field='display_name',
|
|
|
+ attrs={'filter-for': 'power_outlet'}
|
|
|
+ )
|
|
|
+ )
|
|
|
+ livesearch = forms.CharField(
|
|
|
+ required=False,
|
|
|
+ label='PDU',
|
|
|
+ widget=Livesearch(
|
|
|
+ query_key='q',
|
|
|
+ query_url='dcim-api:device_list',
|
|
|
+ field_to_update='pdu'
|
|
|
+ )
|
|
|
+ )
|
|
|
+ power_outlet = forms.ModelChoiceField(
|
|
|
+ queryset=PowerOutlet.objects.all(),
|
|
|
+ label='Outlet',
|
|
|
+ widget=APISelect(
|
|
|
+ api_url='/api/dcim/devices/{{pdu}}/power-outlets/',
|
|
|
+ disabled_indicator='connected_port'
|
|
|
+ )
|
|
|
)
|
|
|
- power_outlet = forms.ModelChoiceField(queryset=PowerOutlet.objects.all(), label='Outlet',
|
|
|
- widget=APISelect(api_url='/api/dcim/devices/{{pdu}}/power-outlets/',
|
|
|
- disabled_indicator='connected_port'))
|
|
|
|
|
|
class Meta:
|
|
|
model = PowerPort
|
|
|
- fields = ['rack', 'pdu', 'livesearch', 'power_outlet', 'connection_status']
|
|
|
+ fields = ['site', 'rack', 'pdu', 'livesearch', 'power_outlet', 'connection_status']
|
|
|
labels = {
|
|
|
'power_outlet': 'Outlet',
|
|
|
'connection_status': 'Status',
|
|
@@ -1039,17 +1141,22 @@ class PowerPortConnectionForm(BootstrapMixin, forms.ModelForm):
|
|
|
if not self.instance.pk:
|
|
|
raise RuntimeError("PowerPortConnectionForm must be initialized with an existing PowerPort instance.")
|
|
|
|
|
|
- self.fields['rack'].queryset = Rack.objects.filter(site=self.instance.device.rack.site)
|
|
|
+ self.initial['site'] = self.instance.device.site
|
|
|
+ self.fields['rack'].queryset = Rack.objects.filter(site=self.instance.device.site)
|
|
|
self.fields['power_outlet'].required = True
|
|
|
self.fields['connection_status'].choices = CONNECTION_STATUS_CHOICES
|
|
|
|
|
|
# Initialize PDU choices
|
|
|
if self.is_bound and self.data.get('rack'):
|
|
|
- self.fields['pdu'].queryset = Device.objects.filter(rack=self.data['rack'], device_type__is_pdu=True)
|
|
|
+ self.fields['pdu'].queryset = Device.objects.filter(rack=self.data['rack'],
|
|
|
+ device_type__is_pdu=True)
|
|
|
elif self.initial.get('rack', None):
|
|
|
- self.fields['pdu'].queryset = Device.objects.filter(rack=self.initial['rack'], device_type__is_pdu=True)
|
|
|
+ self.fields['pdu'].queryset = Device.objects.filter(rack=self.initial['rack'],
|
|
|
+ device_type__is_pdu=True)
|
|
|
else:
|
|
|
- self.fields['pdu'].choices = []
|
|
|
+ self.fields['pdu'].queryset = Device.objects.filter(site=self.instance.device.site,
|
|
|
+ rack__isnull=True,
|
|
|
+ device_type__is_pdu=True)
|
|
|
|
|
|
# Initialize power outlet choices
|
|
|
if self.is_bound:
|
|
@@ -1079,22 +1186,56 @@ class PowerOutletCreateForm(BootstrapMixin, forms.Form):
|
|
|
|
|
|
|
|
|
class PowerOutletConnectionForm(BootstrapMixin, forms.Form):
|
|
|
- rack = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False,
|
|
|
- widget=forms.Select(attrs={'filter-for': 'device'}))
|
|
|
- device = forms.ModelChoiceField(queryset=Device.objects.all(), label='Device', required=False,
|
|
|
- widget=APISelect(api_url='/api/dcim/devices/?rack_id={{rack}}',
|
|
|
- display_field='display_name', attrs={'filter-for': 'port'}))
|
|
|
- livesearch = forms.CharField(required=False, label='Device', widget=Livesearch(
|
|
|
- query_key='q', query_url='dcim-api:device_list', field_to_update='device')
|
|
|
+ site = forms.ModelChoiceField(
|
|
|
+ queryset=Site.objects.all(),
|
|
|
+ widget=forms.HiddenInput()
|
|
|
+ )
|
|
|
+ rack = forms.ModelChoiceField(
|
|
|
+ queryset=Rack.objects.all(),
|
|
|
+ label='Rack',
|
|
|
+ required=False,
|
|
|
+ widget=forms.Select(
|
|
|
+ attrs={'filter-for': 'device', 'nullable': 'true'}
|
|
|
+ )
|
|
|
+ )
|
|
|
+ device = forms.ModelChoiceField(
|
|
|
+ queryset=Device.objects.all(),
|
|
|
+ label='Device',
|
|
|
+ required=False,
|
|
|
+ widget=APISelect(
|
|
|
+ api_url='/api/dcim/devices/?site_id={{site}}&rack_id={{rack}}',
|
|
|
+ display_field='display_name',
|
|
|
+ attrs={'filter-for': 'port'}
|
|
|
+ )
|
|
|
+ )
|
|
|
+ livesearch = forms.CharField(
|
|
|
+ required=False,
|
|
|
+ label='Device',
|
|
|
+ widget=Livesearch(
|
|
|
+ query_key='q',
|
|
|
+ query_url='dcim-api:device_list',
|
|
|
+ field_to_update='device'
|
|
|
+ )
|
|
|
+ )
|
|
|
+ port = forms.ModelChoiceField(
|
|
|
+ queryset=PowerPort.objects.all(),
|
|
|
+ label='Port',
|
|
|
+ widget=APISelect(
|
|
|
+ api_url='/api/dcim/devices/{{device}}/power-ports/',
|
|
|
+ disabled_indicator='power_outlet'
|
|
|
+ )
|
|
|
+ )
|
|
|
+ connection_status = forms.BooleanField(
|
|
|
+ required=False,
|
|
|
+ initial=CONNECTION_STATUS_CONNECTED,
|
|
|
+ label='Status',
|
|
|
+ widget=forms.Select(
|
|
|
+ choices=CONNECTION_STATUS_CHOICES
|
|
|
+ )
|
|
|
)
|
|
|
- port = forms.ModelChoiceField(queryset=PowerPort.objects.all(), label='Port',
|
|
|
- widget=APISelect(api_url='/api/dcim/devices/{{device}}/power-ports/',
|
|
|
- disabled_indicator='power_outlet'))
|
|
|
- connection_status = forms.BooleanField(required=False, initial=CONNECTION_STATUS_CONNECTED, label='Status',
|
|
|
- widget=forms.Select(choices=CONNECTION_STATUS_CHOICES))
|
|
|
|
|
|
class Meta:
|
|
|
- fields = ['rack', 'device', 'livesearch', 'port', 'connection_status']
|
|
|
+ fields = ['site', 'rack', 'device', 'livesearch', 'port', 'connection_status']
|
|
|
labels = {
|
|
|
'connection_status': 'Status',
|
|
|
}
|
|
@@ -1103,7 +1244,8 @@ class PowerOutletConnectionForm(BootstrapMixin, forms.Form):
|
|
|
|
|
|
super(PowerOutletConnectionForm, self).__init__(*args, **kwargs)
|
|
|
|
|
|
- self.fields['rack'].queryset = Rack.objects.filter(site=poweroutlet.device.rack.site)
|
|
|
+ self.initial['site'] = poweroutlet.device.site
|
|
|
+ self.fields['rack'].queryset = Rack.objects.filter(site=poweroutlet.device.site)
|
|
|
|
|
|
# Initialize device choices
|
|
|
if self.is_bound and self.data.get('rack'):
|
|
@@ -1111,7 +1253,8 @@ class PowerOutletConnectionForm(BootstrapMixin, forms.Form):
|
|
|
elif self.initial.get('rack', None):
|
|
|
self.fields['device'].queryset = Device.objects.filter(rack=self.initial['rack'])
|
|
|
else:
|
|
|
- self.fields['device'].choices = []
|
|
|
+ self.fields['device'].queryset = Device.objects.filter(site=poweroutlet.device.site,
|
|
|
+ rack__isnull=True)
|
|
|
|
|
|
# Initialize port choices
|
|
|
if self.is_bound:
|
|
@@ -1158,22 +1301,55 @@ class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm):
|
|
|
#
|
|
|
|
|
|
class InterfaceConnectionForm(BootstrapMixin, forms.ModelForm):
|
|
|
- interface_a = forms.ChoiceField(choices=[], widget=SelectWithDisabled, label='Interface')
|
|
|
- site_b = forms.ModelChoiceField(queryset=Site.objects.all(), label='Site', required=False,
|
|
|
- widget=forms.Select(attrs={'filter-for': 'rack_b'}))
|
|
|
- rack_b = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False,
|
|
|
- widget=APISelect(api_url='/api/dcim/racks/?site_id={{site_b}}',
|
|
|
- attrs={'filter-for': 'device_b'}))
|
|
|
- device_b = forms.ModelChoiceField(queryset=Device.objects.all(), label='Device', required=False,
|
|
|
- widget=APISelect(api_url='/api/dcim/devices/?rack_id={{rack_b}}',
|
|
|
- display_field='display_name',
|
|
|
- attrs={'filter-for': 'interface_b'}))
|
|
|
- livesearch = forms.CharField(required=False, label='Device', widget=Livesearch(
|
|
|
- query_key='q', query_url='dcim-api:device_list', field_to_update='device_b')
|
|
|
+ interface_a = forms.ChoiceField(
|
|
|
+ choices=[],
|
|
|
+ widget=SelectWithDisabled,
|
|
|
+ label='Interface'
|
|
|
+ )
|
|
|
+ site_b = forms.ModelChoiceField(
|
|
|
+ queryset=Site.objects.all(),
|
|
|
+ label='Site',
|
|
|
+ required=False,
|
|
|
+ widget=forms.Select(
|
|
|
+ attrs={'filter-for': 'rack_b'}
|
|
|
+ )
|
|
|
+ )
|
|
|
+ rack_b = forms.ModelChoiceField(
|
|
|
+ queryset=Rack.objects.all(),
|
|
|
+ label='Rack',
|
|
|
+ required=False,
|
|
|
+ widget=APISelect(
|
|
|
+ api_url='/api/dcim/racks/?site_id={{site_b}}',
|
|
|
+ attrs={'filter-for': 'device_b', 'nullable': 'true'}
|
|
|
+ )
|
|
|
+ )
|
|
|
+ device_b = forms.ModelChoiceField(
|
|
|
+ queryset=Device.objects.all(),
|
|
|
+ label='Device',
|
|
|
+ required=False,
|
|
|
+ widget=APISelect(
|
|
|
+ api_url='/api/dcim/devices/?site_id={{site_b}}&rack_id={{rack_b}}',
|
|
|
+ display_field='display_name',
|
|
|
+ attrs={'filter-for': 'interface_b'}
|
|
|
+ )
|
|
|
+ )
|
|
|
+ livesearch = forms.CharField(
|
|
|
+ required=False,
|
|
|
+ label='Device',
|
|
|
+ widget=Livesearch(
|
|
|
+ query_key='q',
|
|
|
+ query_url='dcim-api:device_list',
|
|
|
+ field_to_update='device_b'
|
|
|
+ )
|
|
|
+ )
|
|
|
+ interface_b = forms.ModelChoiceField(
|
|
|
+ queryset=Interface.objects.all(),
|
|
|
+ label='Interface',
|
|
|
+ widget=APISelect(
|
|
|
+ api_url='/api/dcim/devices/{{device_b}}/interfaces/?type=physical',
|
|
|
+ disabled_indicator='is_connected'
|
|
|
+ )
|
|
|
)
|
|
|
- interface_b = forms.ModelChoiceField(queryset=Interface.objects.all(), label='Interface',
|
|
|
- widget=APISelect(api_url='/api/dcim/devices/{{device_b}}/interfaces/?type=physical',
|
|
|
- disabled_indicator='is_connected'))
|
|
|
|
|
|
class Meta:
|
|
|
model = InterfaceConnection
|
|
@@ -1198,11 +1374,15 @@ class InterfaceConnectionForm(BootstrapMixin, forms.ModelForm):
|
|
|
else:
|
|
|
self.fields['rack_b'].choices = []
|
|
|
|
|
|
- # Initialize device_b choices if rack_b is set
|
|
|
+ # Initialize device_b choices if rack_b or site_b is set
|
|
|
if self.is_bound and self.data.get('rack_b'):
|
|
|
self.fields['device_b'].queryset = Device.objects.filter(rack__pk=self.data['rack_b'])
|
|
|
+ elif self.is_bound and self.data.get('site_b'):
|
|
|
+ self.fields['device_b'].queryset = Device.objects.filter(site__pk=self.data['site_b'], rack__isnull=True)
|
|
|
elif self.initial.get('rack_b'):
|
|
|
self.fields['device_b'].queryset = Device.objects.filter(rack=self.initial['rack_b'])
|
|
|
+ elif self.initial.get('site_b'):
|
|
|
+ self.fields['device_b'].queryset = Device.objects.filter(site=self.initial['site_b'], rack__isnull=True)
|
|
|
else:
|
|
|
self.fields['device_b'].choices = []
|
|
|
|
|
@@ -1223,13 +1403,21 @@ class InterfaceConnectionForm(BootstrapMixin, forms.ModelForm):
|
|
|
|
|
|
|
|
|
class InterfaceConnectionCSVForm(forms.Form):
|
|
|
- device_a = FlexibleModelChoiceField(queryset=Device.objects.all(), to_field_name='name',
|
|
|
- error_messages={'invalid_choice': 'Device A not found.'})
|
|
|
+ device_a = FlexibleModelChoiceField(
|
|
|
+ queryset=Device.objects.all(),
|
|
|
+ to_field_name='name',
|
|
|
+ error_messages={'invalid_choice': 'Device A not found.'}
|
|
|
+ )
|
|
|
interface_a = forms.CharField()
|
|
|
- device_b = FlexibleModelChoiceField(queryset=Device.objects.all(), to_field_name='name',
|
|
|
- error_messages={'invalid_choice': 'Device B not found.'})
|
|
|
+ device_b = FlexibleModelChoiceField(
|
|
|
+ queryset=Device.objects.all(),
|
|
|
+ to_field_name='name',
|
|
|
+ error_messages={'invalid_choice': 'Device B not found.'}
|
|
|
+ )
|
|
|
interface_b = forms.CharField()
|
|
|
- status = forms.CharField(validators=[validate_connection_status])
|
|
|
+ status = forms.CharField(
|
|
|
+ validators=[validate_connection_status]
|
|
|
+ )
|
|
|
|
|
|
def clean(self):
|
|
|
|