mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
* Initial work to support rackless devices * Updated device component connection forms * Updated IP address assignment form * Updated circuit termination form * Formatting cleanup * Fixed tests
This commit is contained in:
@@ -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):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user