From 4301c06d177439356d4f4da207f2af1128984293 Mon Sep 17 00:00:00 2001 From: Jonathan Senecal Date: Mon, 8 Jun 2020 23:07:12 -0400 Subject: [PATCH] Refactorization into LabeledComponentForm --- netbox/dcim/forms.py | 242 +++----------------------------------- netbox/utilities/forms.py | 27 +++++ 2 files changed, 44 insertions(+), 225 deletions(-) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 736e129a3..ca706d6f2 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -22,10 +22,10 @@ from tenancy.forms import TenancyFilterForm, TenancyForm from tenancy.models import Tenant, TenantGroup from utilities.forms import ( APISelect, APISelectMultiple, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm, - BulkEditNullBooleanSelect, ColorSelect, CommentField, ConfirmationForm, CSVChoiceField, CSVModelChoiceField, - CSVModelForm, DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableNameField, form_from_model, - JSONField, SelectWithPK, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, - BOOLEAN_WITH_BLANK_CHOICES, + BOOLEAN_WITH_BLANK_CHOICES, BulkEditNullBooleanSelect, ColorSelect, CommentField, ConfirmationForm, CSVChoiceField, + CSVModelChoiceField, CSVModelForm, DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableNameField, + form_from_model, JSONField, LabeledComponentForm, SelectWithPK, SmallTextarea, SlugField, StaticSelect2, + StaticSelect2Multiple, TagFilterField, ) from virtualization.models import Cluster, ClusterGroup, VirtualMachine from .choices import * @@ -1039,34 +1039,15 @@ class ConsolePortTemplateForm(BootstrapMixin, forms.ModelForm): } -class ConsolePortTemplateCreateForm(BootstrapMixin, forms.Form): +class ConsolePortTemplateCreateForm(LabeledComponentForm): device_type = DynamicModelChoiceField( queryset=DeviceType.objects.all() ) - name_pattern = ExpandableNameField( - label='Name' - ) - label_pattern = ExpandableNameField( - label='Label', - required=False - ) type = forms.ChoiceField( choices=add_blank_choice(ConsolePortTypeChoices), widget=StaticSelect2() ) - def clean(self): - - # Validate that the number of ports being created from both the name_pattern and label_pattern are equal - name_pattern_count = len(self.cleaned_data['name_pattern']) - label_pattern_count = len(self.cleaned_data['label_pattern']) - if label_pattern_count and name_pattern_count != label_pattern_count: - raise forms.ValidationError({ - 'label_pattern': 'The provided name pattern will create {} ports, however {} labels will ' - 'be generated. These counts must match.'.format( - name_pattern_count, label_pattern_count) - }) - class ConsolePortTemplateBulkEditForm(BootstrapMixin, BulkEditForm): pk = forms.ModelMultipleChoiceField( @@ -1095,34 +1076,15 @@ class ConsoleServerPortTemplateForm(BootstrapMixin, forms.ModelForm): } -class ConsoleServerPortTemplateCreateForm(BootstrapMixin, forms.Form): +class ConsoleServerPortTemplateCreateForm(LabeledComponentForm): device_type = DynamicModelChoiceField( queryset=DeviceType.objects.all() ) - name_pattern = ExpandableNameField( - label='Name' - ) - label_pattern = ExpandableNameField( - label='Label', - required=False - ) type = forms.ChoiceField( choices=add_blank_choice(ConsolePortTypeChoices), widget=StaticSelect2() ) - def clean(self): - - # Validate that the number of ports being created from both the name_pattern and label_pattern are equal - name_pattern_count = len(self.cleaned_data['name_pattern']) - label_pattern_count = len(self.cleaned_data['label_pattern']) - if label_pattern_count and name_pattern_count != label_pattern_count: - raise forms.ValidationError({ - 'label_pattern': 'The provided name pattern will create {} ports, however {} labels will ' - 'be generated. These counts must match.'.format( - name_pattern_count, label_pattern_count) - }) - class ConsoleServerPortTemplateBulkEditForm(BootstrapMixin, BulkEditForm): pk = forms.ModelMultipleChoiceField( @@ -1151,17 +1113,10 @@ class PowerPortTemplateForm(BootstrapMixin, forms.ModelForm): } -class PowerPortTemplateCreateForm(BootstrapMixin, forms.Form): +class PowerPortTemplateCreateForm(LabeledComponentForm): device_type = DynamicModelChoiceField( queryset=DeviceType.objects.all() ) - name_pattern = ExpandableNameField( - label='Name' - ) - label_pattern = ExpandableNameField( - label='Label', - required=False - ) type = forms.ChoiceField( choices=add_blank_choice(PowerPortTypeChoices), required=False @@ -1177,18 +1132,6 @@ class PowerPortTemplateCreateForm(BootstrapMixin, forms.Form): help_text="Allocated power draw (watts)" ) - def clean(self): - - # Validate that the number of ports being created from both the name_pattern and label_pattern are equal - name_pattern_count = len(self.cleaned_data['name_pattern']) - label_pattern_count = len(self.cleaned_data['label_pattern']) - if label_pattern_count and name_pattern_count != label_pattern_count: - raise forms.ValidationError({ - 'label_pattern': 'The provided name pattern will create {} ports, however {} labels will ' - 'be generated. These counts must match.'.format( - name_pattern_count, label_pattern_count) - }) - class PowerPortTemplateBulkEditForm(BootstrapMixin, BulkEditForm): pk = forms.ModelMultipleChoiceField( @@ -1237,17 +1180,10 @@ class PowerOutletTemplateForm(BootstrapMixin, forms.ModelForm): ) -class PowerOutletTemplateCreateForm(BootstrapMixin, forms.Form): +class PowerOutletTemplateCreateForm(LabeledComponentForm): device_type = DynamicModelChoiceField( queryset=DeviceType.objects.all() ) - name_pattern = ExpandableNameField( - label='Name' - ) - label_pattern = ExpandableNameField( - label='Label', - required=False - ) type = forms.ChoiceField( choices=add_blank_choice(PowerOutletTypeChoices), required=False @@ -1273,18 +1209,6 @@ class PowerOutletTemplateCreateForm(BootstrapMixin, forms.Form): device_type=device_type ) - def clean(self): - - # Validate that the number of ports being created from both the name_pattern and label_pattern are equal - name_pattern_count = len(self.cleaned_data['name_pattern']) - label_pattern_count = len(self.cleaned_data['label_pattern']) - if label_pattern_count and name_pattern_count != label_pattern_count: - raise forms.ValidationError({ - 'label_pattern': 'The provided name pattern will create {} ports, however {} labels will ' - 'be generated. These counts must match.'.format( - name_pattern_count, label_pattern_count) - }) - class PowerOutletTemplateBulkEditForm(BootstrapMixin, BulkEditForm): pk = forms.ModelMultipleChoiceField( @@ -1319,17 +1243,10 @@ class InterfaceTemplateForm(BootstrapMixin, forms.ModelForm): } -class InterfaceTemplateCreateForm(BootstrapMixin, forms.Form): +class InterfaceTemplateCreateForm(LabeledComponentForm): device_type = DynamicModelChoiceField( queryset=DeviceType.objects.all() ) - name_pattern = ExpandableNameField( - label='Name' - ) - label_pattern = ExpandableNameField( - label='Label', - required=False - ) type = forms.ChoiceField( choices=InterfaceTypeChoices, widget=StaticSelect2() @@ -1339,18 +1256,6 @@ class InterfaceTemplateCreateForm(BootstrapMixin, forms.Form): label='Management only' ) - def clean(self): - - # Validate that the number of ports being created from both the name_pattern and label_pattern are equal - name_pattern_count = len(self.cleaned_data['name_pattern']) - label_pattern_count = len(self.cleaned_data['label_pattern']) - if label_pattern_count and name_pattern_count != label_pattern_count: - raise forms.ValidationError({ - 'label_pattern': 'The provided name pattern will create {} interfaces, however {} labels will ' - 'be generated. These counts must match.'.format( - name_pattern_count, label_pattern_count) - }) - class InterfaceTemplateBulkEditForm(BootstrapMixin, BulkEditForm): pk = forms.ModelMultipleChoiceField( @@ -2271,36 +2176,17 @@ class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilt # Bulk device component creation # -class DeviceBulkAddComponentForm(BootstrapMixin, forms.Form): +class DeviceBulkAddComponentForm(LabeledComponentForm): pk = forms.ModelMultipleChoiceField( queryset=Device.objects.all(), widget=forms.MultipleHiddenInput() ) - name_pattern = ExpandableNameField( - label='Name' - ) - label_pattern = ExpandableNameField( - label='Label', - required=False - ) def clean_tags(self): # Because we're feeding TagField data (on the bulk edit form) to another TagField (on the model form), we # must first convert the list of tags to a string. return ','.join(self.cleaned_data.get('tags')) - def clean(self): - - # Validate that the number of ports being created from both the name_pattern and label_pattern are equal - name_pattern_count = len(self.cleaned_data['name_pattern']) - label_pattern_count = len(self.cleaned_data['label_pattern']) - if label_pattern_count and name_pattern_count != label_pattern_count: - raise forms.ValidationError({ - 'label_pattern': 'The provided name pattern will create {} ports, however {} labels will ' - 'be generated. These counts must match.'.format( - name_pattern_count, label_pattern_count) - }) - # # Console ports @@ -2332,17 +2218,10 @@ class ConsolePortForm(BootstrapMixin, forms.ModelForm): } -class ConsolePortCreateForm(BootstrapMixin, forms.Form): +class ConsolePortCreateForm(LabeledComponentForm): device = DynamicModelChoiceField( queryset=Device.objects.prefetch_related('device_type__manufacturer') ) - name_pattern = ExpandableNameField( - label='Name' - ) - label_pattern = ExpandableNameField( - label='Label', - required=False - ) type = forms.ChoiceField( choices=add_blank_choice(ConsolePortTypeChoices), required=False, @@ -2356,18 +2235,6 @@ class ConsolePortCreateForm(BootstrapMixin, forms.Form): required=False ) - def clean(self): - - # Validate that the number of ports being created from both the name_pattern and label_pattern are equal - name_pattern_count = len(self.cleaned_data['name_pattern']) - label_pattern_count = len(self.cleaned_data['label_pattern']) - if label_pattern_count and name_pattern_count != label_pattern_count: - raise forms.ValidationError({ - 'label_pattern': 'The provided name pattern will create {} ports, however {} labels will ' - 'be generated. These counts must match.'.format( - name_pattern_count, label_pattern_count) - }) - class ConsolePortBulkCreateForm( form_from_model(ConsolePort, ['type', 'description', 'tags']), @@ -2434,17 +2301,10 @@ class ConsoleServerPortForm(BootstrapMixin, forms.ModelForm): } -class ConsoleServerPortCreateForm(BootstrapMixin, forms.Form): +class ConsoleServerPortCreateForm(LabeledComponentForm): device = DynamicModelChoiceField( queryset=Device.objects.prefetch_related('device_type__manufacturer') ) - name_pattern = ExpandableNameField( - label='Name' - ) - label_pattern = ExpandableNameField( - label='Label', - required=False - ) type = forms.ChoiceField( choices=add_blank_choice(ConsolePortTypeChoices), required=False, @@ -2458,18 +2318,6 @@ class ConsoleServerPortCreateForm(BootstrapMixin, forms.Form): required=False ) - def clean(self): - - # Validate that the number of ports being created from both the name_pattern and label_pattern are equal - name_pattern_count = len(self.cleaned_data['name_pattern']) - label_pattern_count = len(self.cleaned_data['label_pattern']) - if label_pattern_count and name_pattern_count != label_pattern_count: - raise forms.ValidationError({ - 'label_pattern': 'The provided name pattern will create {} ports, however {} labels will ' - 'be generated. These counts must match.'.format( - name_pattern_count, label_pattern_count) - }) - class ConsoleServerPortBulkCreateForm( form_from_model(ConsoleServerPort, ['type', 'description', 'tags']), @@ -2550,17 +2398,10 @@ class PowerPortForm(BootstrapMixin, forms.ModelForm): } -class PowerPortCreateForm(BootstrapMixin, forms.Form): +class PowerPortCreateForm(LabeledComponentForm): device = DynamicModelChoiceField( queryset=Device.objects.prefetch_related('device_type__manufacturer') ) - name_pattern = ExpandableNameField( - label='Name' - ) - label_pattern = ExpandableNameField( - label='Label', - required=False - ) type = forms.ChoiceField( choices=add_blank_choice(PowerPortTypeChoices), required=False, @@ -2583,17 +2424,6 @@ class PowerPortCreateForm(BootstrapMixin, forms.Form): tags = TagField( required=False ) - def clean(self): - - # Validate that the number of ports being created from both the name_pattern and label_pattern are equal - name_pattern_count = len(self.cleaned_data['name_pattern']) - label_pattern_count = len(self.cleaned_data['label_pattern']) - if label_pattern_count and name_pattern_count != label_pattern_count: - raise forms.ValidationError({ - 'label_pattern': 'The provided name pattern will create {} ports, however {} labels will ' - 'be generated. These counts must match.'.format( - name_pattern_count, label_pattern_count) - }) class PowerPortBulkCreateForm( @@ -2674,17 +2504,10 @@ class PowerOutletForm(BootstrapMixin, forms.ModelForm): ) -class PowerOutletCreateForm(BootstrapMixin, forms.Form): +class PowerOutletCreateForm(LabeledComponentForm): device = DynamicModelChoiceField( queryset=Device.objects.prefetch_related('device_type__manufacturer') ) - name_pattern = ExpandableNameField( - label='Name' - ) - label_pattern = ExpandableNameField( - label='Label', - required=False - ) type = forms.ChoiceField( choices=add_blank_choice(PowerOutletTypeChoices), required=False, @@ -2715,18 +2538,6 @@ class PowerOutletCreateForm(BootstrapMixin, forms.Form): ) self.fields['power_port'].queryset = PowerPort.objects.filter(device=device) - def clean(self): - - # Validate that the number of ports being created from both the name_pattern and label_pattern are equal - name_pattern_count = len(self.cleaned_data['name_pattern']) - label_pattern_count = len(self.cleaned_data['label_pattern']) - if label_pattern_count and name_pattern_count != label_pattern_count: - raise forms.ValidationError({ - 'label_pattern': 'The provided name pattern will create {} ports, however {} labels will ' - 'be generated. These counts must match.'.format( - name_pattern_count, label_pattern_count) - }) - class PowerOutletBulkCreateForm( form_from_model(PowerOutlet, ['type', 'feed_leg', 'description', 'tags']), @@ -2915,17 +2726,11 @@ class InterfaceForm(InterfaceCommonForm, BootstrapMixin, forms.ModelForm): self.fields['tagged_vlans'].widget.add_additional_query_param('site_id', device.site.pk) -class InterfaceCreateForm(BootstrapMixin, InterfaceCommonForm, forms.Form): +class InterfaceCreateForm(InterfaceCommonForm, LabeledComponentForm): + component_type = 'interface' device = DynamicModelChoiceField( queryset=Device.objects.prefetch_related('device_type__manufacturer') ) - name_pattern = ExpandableNameField( - label='Name' - ) - label_pattern = ExpandableNameField( - label='Label', - required=False - ) type = forms.ChoiceField( choices=InterfaceTypeChoices, widget=StaticSelect2(), @@ -3006,25 +2811,12 @@ class InterfaceCreateForm(BootstrapMixin, InterfaceCommonForm, forms.Form): self.fields['untagged_vlan'].widget.add_additional_query_param('site_id', device.site.pk) self.fields['tagged_vlans'].widget.add_additional_query_param('site_id', device.site.pk) - def clean(self): - - # Validate that the number of ports being created from both the name_pattern and label_pattern are equal - name_pattern_count = len(self.cleaned_data['name_pattern']) - label_pattern_count = len(self.cleaned_data['label_pattern']) - if label_pattern_count and name_pattern_count != label_pattern_count: - raise forms.ValidationError({ - 'label_pattern': 'The provided name pattern will create {} interfaces, however {} labels will ' - 'be generated. These counts must match.'.format( - name_pattern_count, label_pattern_count) - }) - - class InterfaceBulkCreateForm( form_from_model(Interface, ['type', 'enabled', 'mtu', 'mgmt_only', 'description', 'tags']), DeviceBulkAddComponentForm ): - pass + component_type = 'interface' class InterfaceBulkEditForm( diff --git a/netbox/utilities/forms.py b/netbox/utilities/forms.py index 3d8dbe33f..8e80168ab 100644 --- a/netbox/utilities/forms.py +++ b/netbox/utilities/forms.py @@ -804,6 +804,33 @@ class ImportForm(BootstrapMixin, forms.Form): }) +class LabeledComponentForm(BootstrapMixin, forms.Form): + """ + Base form for adding label pattern validation to `Create` forms + """ + component_type = 'port' + + name_pattern = ExpandableNameField( + label='Name' + ) + label_pattern = ExpandableNameField( + label='Label', + required=False + ) + + def clean(self): + + # Validate that the number of components being created from both the name_pattern and label_pattern are equal + name_pattern_count = len(self.cleaned_data['name_pattern']) + label_pattern_count = len(self.cleaned_data['label_pattern']) + if label_pattern_count and name_pattern_count != label_pattern_count: + raise forms.ValidationError({ + 'label_pattern': 'The provided name pattern will create {} {}s, however {} labels will ' + 'be generated. These counts must match.'.format( + name_pattern_count, self.component_type, label_pattern_count) + }, code='label_pattern_mismatch') + + class TableConfigForm(BootstrapMixin, forms.Form): """ Form for configuring user's table preferences.