mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-24 08:25:17 -06:00
Initial work on #10247
This commit is contained in:
parent
b702822857
commit
4988c7b7d2
@ -986,47 +986,57 @@ class VCMemberSelectForm(BootstrapMixin, forms.Form):
|
|||||||
# Device component templates
|
# Device component templates
|
||||||
#
|
#
|
||||||
|
|
||||||
|
class ComponentTemplateForm(BootstrapMixin, forms.ModelForm):
|
||||||
|
device_type = DynamicModelChoiceField(
|
||||||
|
queryset=DeviceType.objects.all()
|
||||||
|
)
|
||||||
|
|
||||||
class ConsolePortTemplateForm(BootstrapMixin, forms.ModelForm):
|
|
||||||
|
class ModularComponentTemplateForm(BootstrapMixin, forms.ModelForm):
|
||||||
|
device_type = DynamicModelChoiceField(
|
||||||
|
queryset=DeviceType.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
module_type = DynamicModelChoiceField(
|
||||||
|
queryset=ModuleType.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ConsolePortTemplateForm(ModularComponentTemplateForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ConsolePortTemplate
|
model = ConsolePortTemplate
|
||||||
fields = [
|
fields = [
|
||||||
'device_type', 'module_type', 'name', 'label', 'type', 'description',
|
'device_type', 'module_type', 'name', 'label', 'type', 'description',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device_type': forms.HiddenInput(),
|
|
||||||
'module_type': forms.HiddenInput(),
|
|
||||||
'type': StaticSelect,
|
'type': StaticSelect,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ConsoleServerPortTemplateForm(BootstrapMixin, forms.ModelForm):
|
class ConsoleServerPortTemplateForm(ModularComponentTemplateForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ConsoleServerPortTemplate
|
model = ConsoleServerPortTemplate
|
||||||
fields = [
|
fields = [
|
||||||
'device_type', 'module_type', 'name', 'label', 'type', 'description',
|
'device_type', 'module_type', 'name', 'label', 'type', 'description',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device_type': forms.HiddenInput(),
|
|
||||||
'module_type': forms.HiddenInput(),
|
|
||||||
'type': StaticSelect,
|
'type': StaticSelect,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PowerPortTemplateForm(BootstrapMixin, forms.ModelForm):
|
class PowerPortTemplateForm(ModularComponentTemplateForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = PowerPortTemplate
|
model = PowerPortTemplate
|
||||||
fields = [
|
fields = [
|
||||||
'device_type', 'module_type', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description',
|
'device_type', 'module_type', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device_type': forms.HiddenInput(),
|
|
||||||
'module_type': forms.HiddenInput(),
|
|
||||||
'type': StaticSelect(),
|
'type': StaticSelect(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PowerOutletTemplateForm(BootstrapMixin, forms.ModelForm):
|
class PowerOutletTemplateForm(ModularComponentTemplateForm):
|
||||||
power_port = DynamicModelChoiceField(
|
power_port = DynamicModelChoiceField(
|
||||||
queryset=PowerPortTemplate.objects.all(),
|
queryset=PowerPortTemplate.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
@ -1041,29 +1051,25 @@ class PowerOutletTemplateForm(BootstrapMixin, forms.ModelForm):
|
|||||||
'device_type', 'module_type', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description',
|
'device_type', 'module_type', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device_type': forms.HiddenInput(),
|
|
||||||
'module_type': forms.HiddenInput(),
|
|
||||||
'type': StaticSelect(),
|
'type': StaticSelect(),
|
||||||
'feed_leg': StaticSelect(),
|
'feed_leg': StaticSelect(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class InterfaceTemplateForm(BootstrapMixin, forms.ModelForm):
|
class InterfaceTemplateForm(ModularComponentTemplateForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = InterfaceTemplate
|
model = InterfaceTemplate
|
||||||
fields = [
|
fields = [
|
||||||
'device_type', 'module_type', 'name', 'label', 'type', 'mgmt_only', 'description', 'poe_mode', 'poe_type',
|
'device_type', 'module_type', 'name', 'label', 'type', 'mgmt_only', 'description', 'poe_mode', 'poe_type',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device_type': forms.HiddenInput(),
|
|
||||||
'module_type': forms.HiddenInput(),
|
|
||||||
'type': StaticSelect(),
|
'type': StaticSelect(),
|
||||||
'poe_mode': StaticSelect(),
|
'poe_mode': StaticSelect(),
|
||||||
'poe_type': StaticSelect(),
|
'poe_type': StaticSelect(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class FrontPortTemplateForm(BootstrapMixin, forms.ModelForm):
|
class FrontPortTemplateForm(ModularComponentTemplateForm):
|
||||||
rear_port = DynamicModelChoiceField(
|
rear_port = DynamicModelChoiceField(
|
||||||
queryset=RearPortTemplate.objects.all(),
|
queryset=RearPortTemplate.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
@ -1080,48 +1086,38 @@ class FrontPortTemplateForm(BootstrapMixin, forms.ModelForm):
|
|||||||
'description',
|
'description',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device_type': forms.HiddenInput(),
|
|
||||||
'module_type': forms.HiddenInput(),
|
|
||||||
'type': StaticSelect(),
|
'type': StaticSelect(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class RearPortTemplateForm(BootstrapMixin, forms.ModelForm):
|
class RearPortTemplateForm(ModularComponentTemplateForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RearPortTemplate
|
model = RearPortTemplate
|
||||||
fields = [
|
fields = [
|
||||||
'device_type', 'module_type', 'name', 'label', 'type', 'color', 'positions', 'description',
|
'device_type', 'module_type', 'name', 'label', 'type', 'color', 'positions', 'description',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device_type': forms.HiddenInput(),
|
|
||||||
'module_type': forms.HiddenInput(),
|
|
||||||
'type': StaticSelect(),
|
'type': StaticSelect(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ModuleBayTemplateForm(BootstrapMixin, forms.ModelForm):
|
class ModuleBayTemplateForm(ComponentTemplateForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ModuleBayTemplate
|
model = ModuleBayTemplate
|
||||||
fields = [
|
fields = [
|
||||||
'device_type', 'name', 'label', 'position', 'description',
|
'device_type', 'name', 'label', 'position', 'description',
|
||||||
]
|
]
|
||||||
widgets = {
|
|
||||||
'device_type': forms.HiddenInput(),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class DeviceBayTemplateForm(BootstrapMixin, forms.ModelForm):
|
class DeviceBayTemplateForm(ComponentTemplateForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = DeviceBayTemplate
|
model = DeviceBayTemplate
|
||||||
fields = [
|
fields = [
|
||||||
'device_type', 'name', 'label', 'description',
|
'device_type', 'name', 'label', 'description',
|
||||||
]
|
]
|
||||||
widgets = {
|
|
||||||
'device_type': forms.HiddenInput(),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class InventoryItemTemplateForm(BootstrapMixin, forms.ModelForm):
|
class InventoryItemTemplateForm(ComponentTemplateForm):
|
||||||
parent = DynamicModelChoiceField(
|
parent = DynamicModelChoiceField(
|
||||||
queryset=InventoryItemTemplate.objects.all(),
|
queryset=InventoryItemTemplate.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
@ -1154,9 +1150,6 @@ class InventoryItemTemplateForm(BootstrapMixin, forms.ModelForm):
|
|||||||
'device_type', 'parent', 'name', 'label', 'role', 'manufacturer', 'part_id', 'description',
|
'device_type', 'parent', 'name', 'label', 'role', 'manufacturer', 'part_id', 'description',
|
||||||
'component_type', 'component_id',
|
'component_type', 'component_id',
|
||||||
]
|
]
|
||||||
widgets = {
|
|
||||||
'device_type': forms.HiddenInput(),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -1164,6 +1157,9 @@ class InventoryItemTemplateForm(BootstrapMixin, forms.ModelForm):
|
|||||||
#
|
#
|
||||||
|
|
||||||
class ConsolePortForm(NetBoxModelForm):
|
class ConsolePortForm(NetBoxModelForm):
|
||||||
|
device = DynamicModelChoiceField(
|
||||||
|
queryset=Device.objects.all()
|
||||||
|
)
|
||||||
module = DynamicModelChoiceField(
|
module = DynamicModelChoiceField(
|
||||||
queryset=Module.objects.all(),
|
queryset=Module.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
@ -1178,13 +1174,15 @@ class ConsolePortForm(NetBoxModelForm):
|
|||||||
'device', 'module', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'tags',
|
'device', 'module', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'tags',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device': forms.HiddenInput(),
|
|
||||||
'type': StaticSelect(),
|
'type': StaticSelect(),
|
||||||
'speed': StaticSelect(),
|
'speed': StaticSelect(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ConsoleServerPortForm(NetBoxModelForm):
|
class ConsoleServerPortForm(NetBoxModelForm):
|
||||||
|
device = DynamicModelChoiceField(
|
||||||
|
queryset=Device.objects.all()
|
||||||
|
)
|
||||||
module = DynamicModelChoiceField(
|
module = DynamicModelChoiceField(
|
||||||
queryset=Module.objects.all(),
|
queryset=Module.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
@ -1199,13 +1197,15 @@ class ConsoleServerPortForm(NetBoxModelForm):
|
|||||||
'device', 'module', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'tags',
|
'device', 'module', 'name', 'label', 'type', 'speed', 'mark_connected', 'description', 'tags',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device': forms.HiddenInput(),
|
|
||||||
'type': StaticSelect(),
|
'type': StaticSelect(),
|
||||||
'speed': StaticSelect(),
|
'speed': StaticSelect(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PowerPortForm(NetBoxModelForm):
|
class PowerPortForm(NetBoxModelForm):
|
||||||
|
device = DynamicModelChoiceField(
|
||||||
|
queryset=Device.objects.all()
|
||||||
|
)
|
||||||
module = DynamicModelChoiceField(
|
module = DynamicModelChoiceField(
|
||||||
queryset=Module.objects.all(),
|
queryset=Module.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
@ -1222,12 +1222,14 @@ class PowerPortForm(NetBoxModelForm):
|
|||||||
'tags',
|
'tags',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device': forms.HiddenInput(),
|
|
||||||
'type': StaticSelect(),
|
'type': StaticSelect(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PowerOutletForm(NetBoxModelForm):
|
class PowerOutletForm(NetBoxModelForm):
|
||||||
|
device = DynamicModelChoiceField(
|
||||||
|
queryset=Device.objects.all()
|
||||||
|
)
|
||||||
module = DynamicModelChoiceField(
|
module = DynamicModelChoiceField(
|
||||||
queryset=Module.objects.all(),
|
queryset=Module.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
@ -1250,13 +1252,15 @@ class PowerOutletForm(NetBoxModelForm):
|
|||||||
'tags',
|
'tags',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device': forms.HiddenInput(),
|
|
||||||
'type': StaticSelect(),
|
'type': StaticSelect(),
|
||||||
'feed_leg': StaticSelect(),
|
'feed_leg': StaticSelect(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class InterfaceForm(InterfaceCommonForm, NetBoxModelForm):
|
class InterfaceForm(InterfaceCommonForm, NetBoxModelForm):
|
||||||
|
device = DynamicModelChoiceField(
|
||||||
|
queryset=Device.objects.all()
|
||||||
|
)
|
||||||
module = DynamicModelChoiceField(
|
module = DynamicModelChoiceField(
|
||||||
queryset=Module.objects.all(),
|
queryset=Module.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
@ -1352,7 +1356,6 @@ class InterfaceForm(InterfaceCommonForm, NetBoxModelForm):
|
|||||||
'untagged_vlan', 'tagged_vlans', 'vrf', 'tags',
|
'untagged_vlan', 'tagged_vlans', 'vrf', 'tags',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device': forms.HiddenInput(),
|
|
||||||
'type': StaticSelect(),
|
'type': StaticSelect(),
|
||||||
'speed': SelectSpeedWidget(),
|
'speed': SelectSpeedWidget(),
|
||||||
'poe_mode': StaticSelect(),
|
'poe_mode': StaticSelect(),
|
||||||
@ -1383,6 +1386,9 @@ class InterfaceForm(InterfaceCommonForm, NetBoxModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class FrontPortForm(NetBoxModelForm):
|
class FrontPortForm(NetBoxModelForm):
|
||||||
|
device = DynamicModelChoiceField(
|
||||||
|
queryset=Device.objects.all()
|
||||||
|
)
|
||||||
module = DynamicModelChoiceField(
|
module = DynamicModelChoiceField(
|
||||||
queryset=Module.objects.all(),
|
queryset=Module.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
@ -1404,12 +1410,14 @@ class FrontPortForm(NetBoxModelForm):
|
|||||||
'description', 'tags',
|
'description', 'tags',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device': forms.HiddenInput(),
|
|
||||||
'type': StaticSelect(),
|
'type': StaticSelect(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class RearPortForm(NetBoxModelForm):
|
class RearPortForm(NetBoxModelForm):
|
||||||
|
device = DynamicModelChoiceField(
|
||||||
|
queryset=Device.objects.all()
|
||||||
|
)
|
||||||
module = DynamicModelChoiceField(
|
module = DynamicModelChoiceField(
|
||||||
queryset=Module.objects.all(),
|
queryset=Module.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
@ -1424,33 +1432,32 @@ class RearPortForm(NetBoxModelForm):
|
|||||||
'device', 'module', 'name', 'label', 'type', 'color', 'positions', 'mark_connected', 'description', 'tags',
|
'device', 'module', 'name', 'label', 'type', 'color', 'positions', 'mark_connected', 'description', 'tags',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'device': forms.HiddenInput(),
|
|
||||||
'type': StaticSelect(),
|
'type': StaticSelect(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ModuleBayForm(NetBoxModelForm):
|
class ModuleBayForm(NetBoxModelForm):
|
||||||
|
device = DynamicModelChoiceField(
|
||||||
|
queryset=Device.objects.all()
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ModuleBay
|
model = ModuleBay
|
||||||
fields = [
|
fields = [
|
||||||
'device', 'name', 'label', 'position', 'description', 'tags',
|
'device', 'name', 'label', 'position', 'description', 'tags',
|
||||||
]
|
]
|
||||||
widgets = {
|
|
||||||
'device': forms.HiddenInput(),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class DeviceBayForm(NetBoxModelForm):
|
class DeviceBayForm(NetBoxModelForm):
|
||||||
|
device = DynamicModelChoiceField(
|
||||||
|
queryset=Device.objects.all()
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = DeviceBay
|
model = DeviceBay
|
||||||
fields = [
|
fields = [
|
||||||
'device', 'name', 'label', 'description', 'tags',
|
'device', 'name', 'label', 'description', 'tags',
|
||||||
]
|
]
|
||||||
widgets = {
|
|
||||||
'device': forms.HiddenInput(),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class PopulateDeviceBayForm(BootstrapMixin, forms.Form):
|
class PopulateDeviceBayForm(BootstrapMixin, forms.Form):
|
||||||
|
@ -2,103 +2,108 @@ from django import forms
|
|||||||
|
|
||||||
from dcim.models import *
|
from dcim.models import *
|
||||||
from netbox.forms import NetBoxModelForm
|
from netbox.forms import NetBoxModelForm
|
||||||
from utilities.forms import (
|
from utilities.forms import DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableNameField
|
||||||
BootstrapMixin, DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableNameField,
|
from . import models as model_forms
|
||||||
)
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'ComponentTemplateCreateForm',
|
'ComponentCreateForm',
|
||||||
'DeviceComponentCreateForm',
|
'ConsolePortCreateForm',
|
||||||
|
'ConsolePortTemplateCreateForm',
|
||||||
|
'ConsoleServerPortCreateForm',
|
||||||
|
'ConsoleServerPortTemplateCreateForm',
|
||||||
|
'DeviceBayCreateForm',
|
||||||
|
'DeviceBayTemplateCreateForm',
|
||||||
'FrontPortCreateForm',
|
'FrontPortCreateForm',
|
||||||
'FrontPortTemplateCreateForm',
|
'FrontPortTemplateCreateForm',
|
||||||
|
'InterfaceCreateForm',
|
||||||
|
'InterfaceTemplateCreateForm',
|
||||||
'InventoryItemCreateForm',
|
'InventoryItemCreateForm',
|
||||||
'ModularComponentTemplateCreateForm',
|
'InventoryItemTemplateCreateForm',
|
||||||
'ModuleBayCreateForm',
|
'ModuleBayCreateForm',
|
||||||
'ModuleBayTemplateCreateForm',
|
'ModuleBayTemplateCreateForm',
|
||||||
|
'PowerOutletCreateForm',
|
||||||
|
'PowerOutletTemplateCreateForm',
|
||||||
|
'PowerPortCreateForm',
|
||||||
|
'PowerPortTemplateCreateForm',
|
||||||
|
'RearPortCreateForm',
|
||||||
|
'RearPortTemplateCreateForm',
|
||||||
'VirtualChassisCreateForm',
|
'VirtualChassisCreateForm',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ComponentCreateForm(BootstrapMixin, forms.Form):
|
class ComponentCreateForm(forms.Form):
|
||||||
"""
|
"""
|
||||||
Subclass this form when facilitating the creation of one or more device component or component templates based on
|
Subclass this form when facilitating the creation of one or more device component or component templates based on
|
||||||
a name pattern.
|
a name pattern.
|
||||||
"""
|
"""
|
||||||
name_pattern = ExpandableNameField(
|
name = ExpandableNameField()
|
||||||
label='Name'
|
label = ExpandableNameField(
|
||||||
)
|
|
||||||
label_pattern = ExpandableNameField(
|
|
||||||
label='Label',
|
|
||||||
required=False,
|
required=False,
|
||||||
help_text='Alphanumeric ranges are supported. (Must match the number of names being created.)'
|
help_text='Alphanumeric ranges are supported. (Must match the number of names being created.)'
|
||||||
)
|
)
|
||||||
|
|
||||||
def clean(self):
|
# TODO: Incorporate this validation
|
||||||
super().clean()
|
# def clean(self):
|
||||||
|
# super().clean()
|
||||||
# Validate that all patterned fields generate an equal number of values
|
#
|
||||||
patterned_fields = [
|
# # Validate that all patterned fields generate an equal number of values
|
||||||
field_name for field_name in self.fields if field_name.endswith('_pattern')
|
# patterned_fields = [
|
||||||
]
|
# field_name for field_name in self.fields if field_name.endswith('_pattern')
|
||||||
pattern_count = len(self.cleaned_data['name_pattern'])
|
# ]
|
||||||
for field_name in patterned_fields:
|
# pattern_count = len(self.cleaned_data['name_pattern'])
|
||||||
value_count = len(self.cleaned_data[field_name])
|
# for field_name in patterned_fields:
|
||||||
if self.cleaned_data[field_name] and value_count != pattern_count:
|
# value_count = len(self.cleaned_data[field_name])
|
||||||
raise forms.ValidationError({
|
# if self.cleaned_data[field_name] and value_count != pattern_count:
|
||||||
field_name: f'The provided pattern specifies {value_count} values, but {pattern_count} are '
|
# raise forms.ValidationError({
|
||||||
f'expected.'
|
# field_name: f'The provided pattern specifies {value_count} values, but {pattern_count} are '
|
||||||
}, code='label_pattern_mismatch')
|
# f'expected.'
|
||||||
|
# }, code='label_pattern_mismatch')
|
||||||
|
|
||||||
|
|
||||||
class ComponentTemplateCreateForm(ComponentCreateForm):
|
# class ModularComponentTemplateCreateForm(ComponentCreateForm):
|
||||||
"""
|
# """
|
||||||
Creation form for component templates that can be assigned only to a DeviceType.
|
# Creation form for component templates that can be assigned to either a DeviceType *or* a ModuleType.
|
||||||
"""
|
# """
|
||||||
device_type = DynamicModelChoiceField(
|
# name = ExpandableNameField(
|
||||||
queryset=DeviceType.objects.all(),
|
# label='Name',
|
||||||
)
|
# help_text="""
|
||||||
field_order = ('device_type', 'name_pattern', 'label_pattern')
|
# Alphanumeric ranges are supported for bulk creation. Mixed cases and types within a single range
|
||||||
|
# are not supported. Example: <code>[ge,xe]-0/0/[0-9]</code>. {module} is accepted as a substitution for
|
||||||
|
# the module bay position.
|
||||||
|
# """
|
||||||
|
# )
|
||||||
|
|
||||||
|
|
||||||
class ModularComponentTemplateCreateForm(ComponentCreateForm):
|
#
|
||||||
"""
|
# Device component templates
|
||||||
Creation form for component templates that can be assigned to either a DeviceType *or* a ModuleType.
|
#
|
||||||
"""
|
|
||||||
name_pattern = ExpandableNameField(
|
class ConsolePortTemplateCreateForm(ComponentCreateForm, model_forms.ConsolePortTemplateForm):
|
||||||
label='Name',
|
pass
|
||||||
help_text="""
|
|
||||||
Alphanumeric ranges are supported for bulk creation. Mixed cases and types within a single range
|
|
||||||
are not supported. Example: <code>[ge,xe]-0/0/[0-9]</code>. {module} is accepted as a substitution for
|
|
||||||
the module bay position.
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
device_type = DynamicModelChoiceField(
|
|
||||||
queryset=DeviceType.objects.all(),
|
|
||||||
required=False
|
|
||||||
)
|
|
||||||
module_type = DynamicModelChoiceField(
|
|
||||||
queryset=ModuleType.objects.all(),
|
|
||||||
required=False
|
|
||||||
)
|
|
||||||
field_order = ('device_type', 'module_type', 'name_pattern', 'label_pattern')
|
|
||||||
|
|
||||||
|
|
||||||
class DeviceComponentCreateForm(ComponentCreateForm):
|
class ConsoleServerPortTemplateCreateForm(ComponentCreateForm, model_forms.ConsoleServerPortTemplateForm):
|
||||||
device = DynamicModelChoiceField(
|
pass
|
||||||
queryset=Device.objects.all()
|
|
||||||
)
|
|
||||||
field_order = ('device', 'name_pattern', 'label_pattern')
|
|
||||||
|
|
||||||
|
|
||||||
class FrontPortTemplateCreateForm(ModularComponentTemplateCreateForm):
|
class PowerPortTemplateCreateForm(ComponentCreateForm, model_forms.PowerPortTemplateForm):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PowerOutletTemplateCreateForm(ComponentCreateForm, model_forms.PowerOutletTemplateForm):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceTemplateCreateForm(ComponentCreateForm, model_forms.InterfaceTemplateForm):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FrontPortTemplateCreateForm(ComponentCreateForm, model_forms.FrontPortTemplateForm):
|
||||||
rear_port_set = forms.MultipleChoiceField(
|
rear_port_set = forms.MultipleChoiceField(
|
||||||
choices=[],
|
choices=[],
|
||||||
label='Rear ports',
|
label='Rear ports',
|
||||||
help_text='Select one rear port assignment for each front port being created.',
|
help_text='Select one rear port assignment for each front port being created.',
|
||||||
)
|
)
|
||||||
field_order = (
|
|
||||||
'device_type', 'name_pattern', 'label_pattern', 'rear_port_set',
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
@ -143,15 +148,56 @@ class FrontPortTemplateCreateForm(ModularComponentTemplateCreateForm):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class FrontPortCreateForm(DeviceComponentCreateForm):
|
class RearPortTemplateCreateForm(ComponentCreateForm, model_forms.RearPortTemplateForm):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceBayTemplateCreateForm(ComponentCreateForm, model_forms.DeviceBayTemplateForm):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleBayTemplateCreateForm(ComponentCreateForm, model_forms.ModuleBayTemplateForm):
|
||||||
|
position = ExpandableNameField(
|
||||||
|
label='Position',
|
||||||
|
required=False,
|
||||||
|
help_text='Alphanumeric ranges are supported. (Must match the number of names being created.)'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InventoryItemTemplateCreateForm(ComponentCreateForm, model_forms.InventoryItemTemplateForm):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Device components
|
||||||
|
#
|
||||||
|
|
||||||
|
class ConsolePortCreateForm(ComponentCreateForm, model_forms.ConsolePortForm):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ConsoleServerPortCreateForm(ComponentCreateForm, model_forms.ConsoleServerPortForm):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PowerPortCreateForm(ComponentCreateForm, model_forms.PowerPortForm):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PowerOutletCreateForm(ComponentCreateForm, model_forms.PowerOutletForm):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceCreateForm(ComponentCreateForm, model_forms.InterfaceForm):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FrontPortCreateForm(ComponentCreateForm, model_forms.FrontPortForm):
|
||||||
rear_port_set = forms.MultipleChoiceField(
|
rear_port_set = forms.MultipleChoiceField(
|
||||||
choices=[],
|
choices=[],
|
||||||
label='Rear ports',
|
label='Rear ports',
|
||||||
help_text='Select one rear port assignment for each front port being created.',
|
help_text='Select one rear port assignment for each front port being created.',
|
||||||
)
|
)
|
||||||
field_order = (
|
|
||||||
'device', 'name_pattern', 'label_pattern', 'rear_port_set',
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
@ -189,22 +235,20 @@ class FrontPortCreateForm(DeviceComponentCreateForm):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ModuleBayTemplateCreateForm(ComponentTemplateCreateForm):
|
class RearPortCreateForm(ComponentCreateForm, model_forms.RearPortForm):
|
||||||
position_pattern = ExpandableNameField(
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceBayCreateForm(ComponentCreateForm, model_forms.DeviceBayForm):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleBayCreateForm(ComponentCreateForm, model_forms.ModuleBayForm):
|
||||||
|
position = ExpandableNameField(
|
||||||
label='Position',
|
label='Position',
|
||||||
required=False,
|
required=False,
|
||||||
help_text='Alphanumeric ranges are supported. (Must match the number of names being created.)'
|
help_text='Alphanumeric ranges are supported. (Must match the number of names being created.)'
|
||||||
)
|
)
|
||||||
field_order = ('device_type', 'name_pattern', 'label_pattern', 'position_pattern')
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleBayCreateForm(DeviceComponentCreateForm):
|
|
||||||
position_pattern = ExpandableNameField(
|
|
||||||
label='Position',
|
|
||||||
required=False,
|
|
||||||
help_text='Alphanumeric ranges are supported. (Must match the number of names being created.)'
|
|
||||||
)
|
|
||||||
field_order = ('device', 'name_pattern', 'label_pattern', 'position_pattern')
|
|
||||||
|
|
||||||
|
|
||||||
class InventoryItemCreateForm(ComponentCreateForm):
|
class InventoryItemCreateForm(ComponentCreateForm):
|
||||||
@ -212,6 +256,10 @@ class InventoryItemCreateForm(ComponentCreateForm):
|
|||||||
field_order = ('name_pattern', 'label_pattern')
|
field_order = ('name_pattern', 'label_pattern')
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Virtual chassis
|
||||||
|
#
|
||||||
|
|
||||||
class VirtualChassisCreateForm(NetBoxModelForm):
|
class VirtualChassisCreateForm(NetBoxModelForm):
|
||||||
region = DynamicModelChoiceField(
|
region = DynamicModelChoiceField(
|
||||||
queryset=Region.objects.all(),
|
queryset=Region.objects.all(),
|
||||||
|
@ -132,7 +132,7 @@ class LabelTestCase(TestCase):
|
|||||||
'name_pattern': 'eth[0-9]',
|
'name_pattern': 'eth[0-9]',
|
||||||
'label_pattern': 'Interface[0-9]',
|
'label_pattern': 'Interface[0-9]',
|
||||||
}
|
}
|
||||||
form = DeviceComponentCreateForm(interface_data)
|
form = InterfaceCreateForm(interface_data)
|
||||||
|
|
||||||
self.assertTrue(form.is_valid())
|
self.assertTrue(form.is_valid())
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ class LabelTestCase(TestCase):
|
|||||||
'name_pattern': 'eth[0-9]',
|
'name_pattern': 'eth[0-9]',
|
||||||
'label_pattern': 'Interface[0-1]',
|
'label_pattern': 'Interface[0-1]',
|
||||||
}
|
}
|
||||||
form = DeviceComponentCreateForm(bad_interface_data)
|
form = InterfaceCreateForm(bad_interface_data)
|
||||||
|
|
||||||
self.assertFalse(form.is_valid())
|
self.assertFalse(form.is_valid())
|
||||||
self.assertIn('label_pattern', form.errors)
|
self.assertIn('label_pattern', form.errors)
|
||||||
|
@ -1120,9 +1120,8 @@ class ModuleTypeBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class ConsolePortTemplateCreateView(generic.ComponentCreateView):
|
class ConsolePortTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = ConsolePortTemplate.objects.all()
|
queryset = ConsolePortTemplate.objects.all()
|
||||||
form = forms.ModularComponentTemplateCreateForm
|
form = forms.ConsolePortTemplateCreateForm
|
||||||
model_form = forms.ConsolePortTemplateForm
|
model_form = forms.ConsolePortTemplateForm
|
||||||
template_name = 'dcim/component_template_create.html'
|
|
||||||
|
|
||||||
|
|
||||||
class ConsolePortTemplateEditView(generic.ObjectEditView):
|
class ConsolePortTemplateEditView(generic.ObjectEditView):
|
||||||
@ -1155,9 +1154,8 @@ class ConsolePortTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class ConsoleServerPortTemplateCreateView(generic.ComponentCreateView):
|
class ConsoleServerPortTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = ConsoleServerPortTemplate.objects.all()
|
queryset = ConsoleServerPortTemplate.objects.all()
|
||||||
form = forms.ModularComponentTemplateCreateForm
|
form = forms.ConsoleServerPortTemplateCreateForm
|
||||||
model_form = forms.ConsoleServerPortTemplateForm
|
model_form = forms.ConsoleServerPortTemplateForm
|
||||||
template_name = 'dcim/component_template_create.html'
|
|
||||||
|
|
||||||
|
|
||||||
class ConsoleServerPortTemplateEditView(generic.ObjectEditView):
|
class ConsoleServerPortTemplateEditView(generic.ObjectEditView):
|
||||||
@ -1190,9 +1188,8 @@ class ConsoleServerPortTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class PowerPortTemplateCreateView(generic.ComponentCreateView):
|
class PowerPortTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = PowerPortTemplate.objects.all()
|
queryset = PowerPortTemplate.objects.all()
|
||||||
form = forms.ModularComponentTemplateCreateForm
|
form = forms.PowerPortTemplateCreateForm
|
||||||
model_form = forms.PowerPortTemplateForm
|
model_form = forms.PowerPortTemplateForm
|
||||||
template_name = 'dcim/component_template_create.html'
|
|
||||||
|
|
||||||
|
|
||||||
class PowerPortTemplateEditView(generic.ObjectEditView):
|
class PowerPortTemplateEditView(generic.ObjectEditView):
|
||||||
@ -1225,9 +1222,8 @@ class PowerPortTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class PowerOutletTemplateCreateView(generic.ComponentCreateView):
|
class PowerOutletTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = PowerOutletTemplate.objects.all()
|
queryset = PowerOutletTemplate.objects.all()
|
||||||
form = forms.ModularComponentTemplateCreateForm
|
form = forms.PowerOutletTemplateCreateForm
|
||||||
model_form = forms.PowerOutletTemplateForm
|
model_form = forms.PowerOutletTemplateForm
|
||||||
template_name = 'dcim/component_template_create.html'
|
|
||||||
|
|
||||||
|
|
||||||
class PowerOutletTemplateEditView(generic.ObjectEditView):
|
class PowerOutletTemplateEditView(generic.ObjectEditView):
|
||||||
@ -1260,9 +1256,8 @@ class PowerOutletTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class InterfaceTemplateCreateView(generic.ComponentCreateView):
|
class InterfaceTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = InterfaceTemplate.objects.all()
|
queryset = InterfaceTemplate.objects.all()
|
||||||
form = forms.ModularComponentTemplateCreateForm
|
form = forms.InterfaceTemplateCreateForm
|
||||||
model_form = forms.InterfaceTemplateForm
|
model_form = forms.InterfaceTemplateForm
|
||||||
template_name = 'dcim/component_template_create.html'
|
|
||||||
|
|
||||||
|
|
||||||
class InterfaceTemplateEditView(generic.ObjectEditView):
|
class InterfaceTemplateEditView(generic.ObjectEditView):
|
||||||
@ -1297,15 +1292,6 @@ class FrontPortTemplateCreateView(generic.ComponentCreateView):
|
|||||||
queryset = FrontPortTemplate.objects.all()
|
queryset = FrontPortTemplate.objects.all()
|
||||||
form = forms.FrontPortTemplateCreateForm
|
form = forms.FrontPortTemplateCreateForm
|
||||||
model_form = forms.FrontPortTemplateForm
|
model_form = forms.FrontPortTemplateForm
|
||||||
template_name = 'dcim/frontporttemplate_create.html'
|
|
||||||
|
|
||||||
def initialize_forms(self, request):
|
|
||||||
form, model_form = super().initialize_forms(request)
|
|
||||||
|
|
||||||
model_form.fields.pop('rear_port')
|
|
||||||
model_form.fields.pop('rear_port_position')
|
|
||||||
|
|
||||||
return form, model_form
|
|
||||||
|
|
||||||
|
|
||||||
class FrontPortTemplateEditView(generic.ObjectEditView):
|
class FrontPortTemplateEditView(generic.ObjectEditView):
|
||||||
@ -1338,9 +1324,8 @@ class FrontPortTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class RearPortTemplateCreateView(generic.ComponentCreateView):
|
class RearPortTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = RearPortTemplate.objects.all()
|
queryset = RearPortTemplate.objects.all()
|
||||||
form = forms.ModularComponentTemplateCreateForm
|
form = forms.RearPortTemplateCreateForm
|
||||||
model_form = forms.RearPortTemplateForm
|
model_form = forms.RearPortTemplateForm
|
||||||
template_name = 'dcim/component_template_create.html'
|
|
||||||
|
|
||||||
|
|
||||||
class RearPortTemplateEditView(generic.ObjectEditView):
|
class RearPortTemplateEditView(generic.ObjectEditView):
|
||||||
@ -1375,7 +1360,6 @@ class ModuleBayTemplateCreateView(generic.ComponentCreateView):
|
|||||||
queryset = ModuleBayTemplate.objects.all()
|
queryset = ModuleBayTemplate.objects.all()
|
||||||
form = forms.ModuleBayTemplateCreateForm
|
form = forms.ModuleBayTemplateCreateForm
|
||||||
model_form = forms.ModuleBayTemplateForm
|
model_form = forms.ModuleBayTemplateForm
|
||||||
template_name = 'dcim/modulebaytemplate_create.html'
|
|
||||||
patterned_fields = ('name', 'label', 'position')
|
patterned_fields = ('name', 'label', 'position')
|
||||||
|
|
||||||
|
|
||||||
@ -1409,9 +1393,8 @@ class ModuleBayTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class DeviceBayTemplateCreateView(generic.ComponentCreateView):
|
class DeviceBayTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = DeviceBayTemplate.objects.all()
|
queryset = DeviceBayTemplate.objects.all()
|
||||||
form = forms.ComponentTemplateCreateForm
|
form = forms.DeviceBayTemplateCreateForm
|
||||||
model_form = forms.DeviceBayTemplateForm
|
model_form = forms.DeviceBayTemplateForm
|
||||||
template_name = 'dcim/component_template_create.html'
|
|
||||||
|
|
||||||
|
|
||||||
class DeviceBayTemplateEditView(generic.ObjectEditView):
|
class DeviceBayTemplateEditView(generic.ObjectEditView):
|
||||||
@ -1444,9 +1427,8 @@ class DeviceBayTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class InventoryItemTemplateCreateView(generic.ComponentCreateView):
|
class InventoryItemTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = InventoryItemTemplate.objects.all()
|
queryset = InventoryItemTemplate.objects.all()
|
||||||
form = forms.ModularComponentTemplateCreateForm
|
form = forms.InventoryItemTemplateCreateForm
|
||||||
model_form = forms.InventoryItemTemplateForm
|
model_form = forms.InventoryItemTemplateForm
|
||||||
template_name = 'dcim/inventoryitemtemplate_create.html'
|
|
||||||
|
|
||||||
def alter_object(self, instance, request):
|
def alter_object(self, instance, request):
|
||||||
# Set component (if any)
|
# Set component (if any)
|
||||||
@ -1874,7 +1856,7 @@ class ConsolePortView(generic.ObjectView):
|
|||||||
|
|
||||||
class ConsolePortCreateView(generic.ComponentCreateView):
|
class ConsolePortCreateView(generic.ComponentCreateView):
|
||||||
queryset = ConsolePort.objects.all()
|
queryset = ConsolePort.objects.all()
|
||||||
form = forms.DeviceComponentCreateForm
|
form = forms.ConsolePortCreateForm
|
||||||
model_form = forms.ConsolePortForm
|
model_form = forms.ConsolePortForm
|
||||||
|
|
||||||
|
|
||||||
@ -1933,7 +1915,7 @@ class ConsoleServerPortView(generic.ObjectView):
|
|||||||
|
|
||||||
class ConsoleServerPortCreateView(generic.ComponentCreateView):
|
class ConsoleServerPortCreateView(generic.ComponentCreateView):
|
||||||
queryset = ConsoleServerPort.objects.all()
|
queryset = ConsoleServerPort.objects.all()
|
||||||
form = forms.DeviceComponentCreateForm
|
form = forms.ConsoleServerPortCreateForm
|
||||||
model_form = forms.ConsoleServerPortForm
|
model_form = forms.ConsoleServerPortForm
|
||||||
|
|
||||||
|
|
||||||
@ -1992,7 +1974,7 @@ class PowerPortView(generic.ObjectView):
|
|||||||
|
|
||||||
class PowerPortCreateView(generic.ComponentCreateView):
|
class PowerPortCreateView(generic.ComponentCreateView):
|
||||||
queryset = PowerPort.objects.all()
|
queryset = PowerPort.objects.all()
|
||||||
form = forms.DeviceComponentCreateForm
|
form = forms.PowerPortCreateForm
|
||||||
model_form = forms.PowerPortForm
|
model_form = forms.PowerPortForm
|
||||||
|
|
||||||
|
|
||||||
@ -2051,7 +2033,7 @@ class PowerOutletView(generic.ObjectView):
|
|||||||
|
|
||||||
class PowerOutletCreateView(generic.ComponentCreateView):
|
class PowerOutletCreateView(generic.ComponentCreateView):
|
||||||
queryset = PowerOutlet.objects.all()
|
queryset = PowerOutlet.objects.all()
|
||||||
form = forms.DeviceComponentCreateForm
|
form = forms.PowerOutletCreateForm
|
||||||
model_form = forms.PowerOutletForm
|
model_form = forms.PowerOutletForm
|
||||||
|
|
||||||
|
|
||||||
@ -2154,42 +2136,13 @@ class InterfaceView(generic.ObjectView):
|
|||||||
|
|
||||||
class InterfaceCreateView(generic.ComponentCreateView):
|
class InterfaceCreateView(generic.ComponentCreateView):
|
||||||
queryset = Interface.objects.all()
|
queryset = Interface.objects.all()
|
||||||
form = forms.DeviceComponentCreateForm
|
form = forms.InterfaceCreateForm
|
||||||
model_form = forms.InterfaceForm
|
model_form = forms.InterfaceForm
|
||||||
# template_name = 'dcim/interface_create.html'
|
|
||||||
|
|
||||||
# TODO: Figure out what to do with this
|
|
||||||
# def post(self, request):
|
|
||||||
# """
|
|
||||||
# Override inherited post() method to handle request to assign newly created
|
|
||||||
# interface objects (first object) to an IP Address object.
|
|
||||||
# """
|
|
||||||
# form = self.form(request.POST, initial=request.GET)
|
|
||||||
# new_objs = self.validate_form(request, form)
|
|
||||||
#
|
|
||||||
# if form.is_valid() and not form.errors:
|
|
||||||
# if '_addanother' in request.POST:
|
|
||||||
# return redirect(request.get_full_path())
|
|
||||||
# elif new_objs is not None and '_assignip' in request.POST and len(new_objs) >= 1 and \
|
|
||||||
# request.user.has_perm('ipam.add_ipaddress'):
|
|
||||||
# first_obj = new_objs[0].pk
|
|
||||||
# return redirect(
|
|
||||||
# f'/ipam/ip-addresses/add/?interface={first_obj}&return_url={self.get_return_url(request)}'
|
|
||||||
# )
|
|
||||||
# else:
|
|
||||||
# return redirect(self.get_return_url(request))
|
|
||||||
#
|
|
||||||
# return render(request, self.template_name, {
|
|
||||||
# 'obj_type': self.queryset.model._meta.verbose_name,
|
|
||||||
# 'form': form,
|
|
||||||
# 'return_url': self.get_return_url(request),
|
|
||||||
# })
|
|
||||||
|
|
||||||
|
|
||||||
class InterfaceEditView(generic.ObjectEditView):
|
class InterfaceEditView(generic.ObjectEditView):
|
||||||
queryset = Interface.objects.all()
|
queryset = Interface.objects.all()
|
||||||
form = forms.InterfaceForm
|
form = forms.InterfaceForm
|
||||||
template_name = 'dcim/interface_edit.html'
|
|
||||||
|
|
||||||
|
|
||||||
class InterfaceDeleteView(generic.ObjectDeleteView):
|
class InterfaceDeleteView(generic.ObjectDeleteView):
|
||||||
@ -2244,14 +2197,6 @@ class FrontPortCreateView(generic.ComponentCreateView):
|
|||||||
form = forms.FrontPortCreateForm
|
form = forms.FrontPortCreateForm
|
||||||
model_form = forms.FrontPortForm
|
model_form = forms.FrontPortForm
|
||||||
|
|
||||||
def initialize_forms(self, request):
|
|
||||||
form, model_form = super().initialize_forms(request)
|
|
||||||
|
|
||||||
model_form.fields.pop('rear_port')
|
|
||||||
model_form.fields.pop('rear_port_position')
|
|
||||||
|
|
||||||
return form, model_form
|
|
||||||
|
|
||||||
|
|
||||||
class FrontPortEditView(generic.ObjectEditView):
|
class FrontPortEditView(generic.ObjectEditView):
|
||||||
queryset = FrontPort.objects.all()
|
queryset = FrontPort.objects.all()
|
||||||
@ -2308,7 +2253,7 @@ class RearPortView(generic.ObjectView):
|
|||||||
|
|
||||||
class RearPortCreateView(generic.ComponentCreateView):
|
class RearPortCreateView(generic.ComponentCreateView):
|
||||||
queryset = RearPort.objects.all()
|
queryset = RearPort.objects.all()
|
||||||
form = forms.DeviceComponentCreateForm
|
form = forms.RearPortCreateForm
|
||||||
model_form = forms.RearPortForm
|
model_form = forms.RearPortForm
|
||||||
|
|
||||||
|
|
||||||
@ -2423,7 +2368,7 @@ class DeviceBayView(generic.ObjectView):
|
|||||||
|
|
||||||
class DeviceBayCreateView(generic.ComponentCreateView):
|
class DeviceBayCreateView(generic.ComponentCreateView):
|
||||||
queryset = DeviceBay.objects.all()
|
queryset = DeviceBay.objects.all()
|
||||||
form = forms.DeviceComponentCreateForm
|
form = forms.DeviceBayCreateForm
|
||||||
model_form = forms.DeviceBayForm
|
model_form = forms.DeviceBayForm
|
||||||
|
|
||||||
|
|
||||||
@ -2552,7 +2497,6 @@ class InventoryItemCreateView(generic.ComponentCreateView):
|
|||||||
queryset = InventoryItem.objects.all()
|
queryset = InventoryItem.objects.all()
|
||||||
form = forms.InventoryItemCreateForm
|
form = forms.InventoryItemCreateForm
|
||||||
model_form = forms.InventoryItemForm
|
model_form = forms.InventoryItemForm
|
||||||
template_name = 'dcim/inventoryitem_create.html'
|
|
||||||
|
|
||||||
def alter_object(self, instance, request):
|
def alter_object(self, instance, request):
|
||||||
# Set component (if any)
|
# Set component (if any)
|
||||||
|
@ -538,7 +538,7 @@ class ComponentCreateView(GetReturnURLMixin, BaseObjectView):
|
|||||||
"""
|
"""
|
||||||
Add one or more components (e.g. interfaces, console ports, etc.) to a Device or VirtualMachine.
|
Add one or more components (e.g. interfaces, console ports, etc.) to a Device or VirtualMachine.
|
||||||
"""
|
"""
|
||||||
template_name = 'dcim/component_create.html'
|
template_name = 'generic/object_edit.html'
|
||||||
form = None
|
form = None
|
||||||
model_form = None
|
model_form = None
|
||||||
patterned_fields = ('name', 'label')
|
patterned_fields = ('name', 'label')
|
||||||
@ -549,44 +549,38 @@ class ComponentCreateView(GetReturnURLMixin, BaseObjectView):
|
|||||||
def alter_object(self, instance, request):
|
def alter_object(self, instance, request):
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
def initialize_forms(self, request):
|
def initialize_form(self, request):
|
||||||
data = request.POST if request.method == 'POST' else None
|
data = request.POST if request.method == 'POST' else None
|
||||||
initial_data = normalize_querydict(request.GET)
|
initial_data = normalize_querydict(request.GET)
|
||||||
|
|
||||||
form = self.form(data=data, initial=request.GET)
|
form = self.form(data=data, initial=initial_data)
|
||||||
model_form = self.model_form(data=data, initial=initial_data)
|
|
||||||
|
|
||||||
# These fields will be set from the pattern values
|
return form
|
||||||
for field_name in self.patterned_fields:
|
|
||||||
model_form.fields[field_name].widget = HiddenInput()
|
|
||||||
|
|
||||||
return form, model_form
|
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
form, model_form = self.initialize_forms(request)
|
form = self.initialize_form(request)
|
||||||
instance = self.alter_object(self.queryset.model(), request)
|
instance = self.alter_object(self.queryset.model(), request)
|
||||||
|
|
||||||
return render(request, self.template_name, {
|
return render(request, self.template_name, {
|
||||||
'object': instance,
|
'object': instance,
|
||||||
'replication_form': form,
|
'form': form,
|
||||||
'form': model_form,
|
|
||||||
'return_url': self.get_return_url(request),
|
'return_url': self.get_return_url(request),
|
||||||
})
|
})
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
logger = logging.getLogger('netbox.views.ComponentCreateView')
|
logger = logging.getLogger('netbox.views.ComponentCreateView')
|
||||||
form, model_form = self.initialize_forms(request)
|
form = self.initialize_form(request)
|
||||||
instance = self.alter_object(self.queryset.model(), request)
|
instance = self.alter_object(self.queryset.model(), request)
|
||||||
|
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
new_components = []
|
new_components = []
|
||||||
data = deepcopy(request.POST)
|
data = deepcopy(request.POST)
|
||||||
pattern_count = len(form.cleaned_data[f'{self.patterned_fields[0]}_pattern'])
|
pattern_count = len(form.cleaned_data[self.patterned_fields[0]])
|
||||||
|
|
||||||
for i in range(pattern_count):
|
for i in range(pattern_count):
|
||||||
for field_name in self.patterned_fields:
|
for field_name in self.patterned_fields:
|
||||||
if form.cleaned_data.get(f'{field_name}_pattern'):
|
if form.cleaned_data.get(field_name):
|
||||||
data[field_name] = form.cleaned_data[f'{field_name}_pattern'][i]
|
data[field_name] = form.cleaned_data[field_name][i]
|
||||||
|
|
||||||
if hasattr(form, 'get_iterative_data'):
|
if hasattr(form, 'get_iterative_data'):
|
||||||
data.update(form.get_iterative_data(i))
|
data.update(form.get_iterative_data(i))
|
||||||
@ -626,7 +620,6 @@ class ComponentCreateView(GetReturnURLMixin, BaseObjectView):
|
|||||||
|
|
||||||
return render(request, self.template_name, {
|
return render(request, self.template_name, {
|
||||||
'object': instance,
|
'object': instance,
|
||||||
'replication_form': form,
|
'form': form,
|
||||||
'form': model_form,
|
|
||||||
'return_url': self.get_return_url(request),
|
'return_url': self.get_return_url(request),
|
||||||
})
|
})
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
{% extends 'generic/object_edit.html' %}
|
|
||||||
{% load form_helpers %}
|
|
||||||
|
|
||||||
{% block form %}
|
|
||||||
{% if form.module_type %}
|
|
||||||
<div class="row mb-2">
|
|
||||||
<div class="offset-sm-3">
|
|
||||||
<ul class="nav nav-pills" role="tablist">
|
|
||||||
<li role="presentation" class="nav-item">
|
|
||||||
<button role="tab" type="button" id="devicetype_tab" data-bs-toggle="tab" aria-controls="devicetype" data-bs-target="#devicetype" class="nav-link {% if not form.initial.module_type %}active{% endif %}">
|
|
||||||
Device Type
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li role="presentation" class="nav-item">
|
|
||||||
<button role="tab" type="button" id="moduletype_tab" data-bs-toggle="tab" aria-controls="moduletype" data-bs-target="#moduletype" class="nav-link {% if form.initial.module_type %}active{% endif %}">
|
|
||||||
Module Type
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tab-content p-0 border-0">
|
|
||||||
<div class="tab-pane {% if not form.initial.module_type %}active{% endif %}" id="devicetype" role="tabpanel">
|
|
||||||
{% render_field replication_form.device_type %}
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane {% if form.initial.module_type %}active{% endif %}" id="moduletype" role="tabpanel">
|
|
||||||
{% render_field replication_form.module_type %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
{% render_field replication_form.device_type %}
|
|
||||||
{% endif %}
|
|
||||||
{% block replication_fields %}
|
|
||||||
{% render_field replication_form.name_pattern %}
|
|
||||||
{% render_field replication_form.label_pattern %}
|
|
||||||
{% endblock replication_fields %}
|
|
||||||
{{ block.super }}
|
|
||||||
{% endblock form %}
|
|
@ -1,7 +0,0 @@
|
|||||||
{% extends 'dcim/component_template_create.html' %}
|
|
||||||
{% load form_helpers %}
|
|
||||||
|
|
||||||
{% block replication_fields %}
|
|
||||||
{{ block.super }}
|
|
||||||
{% render_field replication_form.rear_port_set %}
|
|
||||||
{% endblock replication_fields %}
|
|
@ -1,17 +0,0 @@
|
|||||||
{% extends 'dcim/component_create.html' %}
|
|
||||||
{% load helpers %}
|
|
||||||
{% load form_helpers %}
|
|
||||||
|
|
||||||
{% block replication_fields %}
|
|
||||||
{{ block.super }}
|
|
||||||
{% if object.component %}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">
|
|
||||||
{{ object.component|meta:"verbose_name"|bettertitle }}
|
|
||||||
</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ object.component }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock replication_fields %}
|
|
@ -1,17 +0,0 @@
|
|||||||
{% extends 'dcim/component_template_create.html' %}
|
|
||||||
{% load helpers %}
|
|
||||||
{% load form_helpers %}
|
|
||||||
|
|
||||||
{% block replication_fields %}
|
|
||||||
{{ block.super }}
|
|
||||||
{% if object.component %}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">
|
|
||||||
{{ object.component|meta:"verbose_name"|bettertitle }}
|
|
||||||
</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ object.component }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock replication_fields %}
|
|
@ -1,7 +0,0 @@
|
|||||||
{% extends 'dcim/component_template_create.html' %}
|
|
||||||
{% load form_helpers %}
|
|
||||||
|
|
||||||
{% block replication_fields %}
|
|
||||||
{{ block.super }}
|
|
||||||
{% render_field replication_form.position_pattern %}
|
|
||||||
{% endblock replication_fields %}
|
|
@ -1,69 +0,0 @@
|
|||||||
{% extends 'generic/object_edit.html' %}
|
|
||||||
{% load form_helpers %}
|
|
||||||
|
|
||||||
{% block form %}
|
|
||||||
{# Render hidden fields #}
|
|
||||||
{% for field in form.hidden_fields %}
|
|
||||||
{{ field }}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<div class="field-group my-5">
|
|
||||||
<div class="row mb-2">
|
|
||||||
<h5 class="offset-sm-3">Interface</h5>
|
|
||||||
</div>
|
|
||||||
{% if form.instance.virtual_machine %}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end required" for="id_device">Virtual Machine</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ form.instance.virtual_machine }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% render_field form.name %}
|
|
||||||
{% render_field form.description %}
|
|
||||||
{% render_field form.tags %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-group my-5">
|
|
||||||
<div class="row mb-2">
|
|
||||||
<h5 class="offset-sm-3">Addressing</h5>
|
|
||||||
</div>
|
|
||||||
{% render_field form.vrf %}
|
|
||||||
{% render_field form.mac_address %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-group my-5">
|
|
||||||
<div class="row mb-2">
|
|
||||||
<h5 class="offset-sm-3">Operation</h5>
|
|
||||||
</div>
|
|
||||||
{% render_field form.mtu %}
|
|
||||||
{% render_field form.enabled %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-group my-5">
|
|
||||||
<div class="row mb-2">
|
|
||||||
<h5 class="offset-sm-3">Related Interfaces</h5>
|
|
||||||
</div>
|
|
||||||
{% render_field form.parent %}
|
|
||||||
{% render_field form.bridge %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-group my-5">
|
|
||||||
<div class="row mb-2">
|
|
||||||
<h5 class="offset-sm-3">802.1Q Switching</h5>
|
|
||||||
</div>
|
|
||||||
{% render_field form.mode %}
|
|
||||||
{% render_field form.vlan_group %}
|
|
||||||
{% render_field form.untagged_vlan %}
|
|
||||||
{% render_field form.tagged_vlans %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if form.custom_fields %}
|
|
||||||
<div class="field-group my-5">
|
|
||||||
<div class="row mb-2">
|
|
||||||
<h5 class="offset-sm-3">Custom Fields</h5>
|
|
||||||
</div>
|
|
||||||
{% render_custom_fields form %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
@ -5,7 +5,6 @@ from django.core.exceptions import ValidationError
|
|||||||
from dcim.forms.common import InterfaceCommonForm
|
from dcim.forms.common import InterfaceCommonForm
|
||||||
from dcim.forms.models import INTERFACE_MODE_HELP_TEXT
|
from dcim.forms.models import INTERFACE_MODE_HELP_TEXT
|
||||||
from dcim.models import Device, DeviceRole, Platform, Rack, Region, Site, SiteGroup
|
from dcim.models import Device, DeviceRole, Platform, Rack, Region, Site, SiteGroup
|
||||||
from extras.models import Tag
|
|
||||||
from ipam.models import IPAddress, VLAN, VLANGroup, VRF
|
from ipam.models import IPAddress, VLAN, VLANGroup, VRF
|
||||||
from netbox.forms import NetBoxModelForm
|
from netbox.forms import NetBoxModelForm
|
||||||
from tenancy.forms import TenancyForm
|
from tenancy.forms import TenancyForm
|
||||||
@ -278,6 +277,9 @@ class VirtualMachineForm(TenancyForm, NetBoxModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
|
class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
|
||||||
|
virtual_machine = DynamicModelChoiceField(
|
||||||
|
queryset=VirtualMachine.objects.all()
|
||||||
|
)
|
||||||
parent = DynamicModelChoiceField(
|
parent = DynamicModelChoiceField(
|
||||||
queryset=VMInterface.objects.all(),
|
queryset=VMInterface.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
@ -338,7 +340,6 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
|
|||||||
'vlan_group', 'untagged_vlan', 'tagged_vlans', 'vrf', 'tags',
|
'vlan_group', 'untagged_vlan', 'tagged_vlans', 'vrf', 'tags',
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'virtual_machine': forms.HiddenInput(),
|
|
||||||
'mode': StaticSelect()
|
'mode': StaticSelect()
|
||||||
}
|
}
|
||||||
labels = {
|
labels = {
|
||||||
@ -347,3 +348,10 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
|
|||||||
help_texts = {
|
help_texts = {
|
||||||
'mode': INTERFACE_MODE_HELP_TEXT,
|
'mode': INTERFACE_MODE_HELP_TEXT,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
# Disable reassignment of VirtualMachine when editing an existing instance
|
||||||
|
if self.instance.pk:
|
||||||
|
self.fields['virtual_machine'].disabled = True
|
||||||
|
@ -1,17 +1,10 @@
|
|||||||
from django import forms
|
from utilities.forms import ExpandableNameField
|
||||||
|
from .models import VMInterfaceForm
|
||||||
from utilities.forms import BootstrapMixin, DynamicModelChoiceField, ExpandableNameField
|
|
||||||
from .models import VirtualMachine
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'VMInterfaceCreateForm',
|
'VMInterfaceCreateForm',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class VMInterfaceCreateForm(BootstrapMixin, forms.Form):
|
class VMInterfaceCreateForm(VMInterfaceForm):
|
||||||
virtual_machine = DynamicModelChoiceField(
|
name = ExpandableNameField()
|
||||||
queryset=VirtualMachine.objects.all()
|
|
||||||
)
|
|
||||||
name_pattern = ExpandableNameField(
|
|
||||||
label='Name'
|
|
||||||
)
|
|
||||||
|
@ -457,7 +457,6 @@ class VMInterfaceCreateView(generic.ComponentCreateView):
|
|||||||
class VMInterfaceEditView(generic.ObjectEditView):
|
class VMInterfaceEditView(generic.ObjectEditView):
|
||||||
queryset = VMInterface.objects.all()
|
queryset = VMInterface.objects.all()
|
||||||
form = forms.VMInterfaceForm
|
form = forms.VMInterfaceForm
|
||||||
template_name = 'virtualization/vminterface_edit.html'
|
|
||||||
|
|
||||||
|
|
||||||
class VMInterfaceDeleteView(generic.ObjectDeleteView):
|
class VMInterfaceDeleteView(generic.ObjectDeleteView):
|
||||||
|
Loading…
Reference in New Issue
Block a user