From c5dc075fb02e3d67d30275b85925ea6e88c340f5 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 18 Jun 2020 11:59:24 -0400 Subject: [PATCH] Fixes #4775: Allow selecting an alternate device type when creating component templates --- docs/release-notes/version-2.8.md | 1 + netbox/dcim/forms.py | 89 ++++++++++++------------------- netbox/utilities/views.py | 4 ++ 3 files changed, 38 insertions(+), 56 deletions(-) diff --git a/docs/release-notes/version-2.8.md b/docs/release-notes/version-2.8.md index 366241390..ca264806b 100644 --- a/docs/release-notes/version-2.8.md +++ b/docs/release-notes/version-2.8.md @@ -6,6 +6,7 @@ * [#4766](https://github.com/netbox-community/netbox/issues/4766) - Fix redirect after login when `next` is not specified * [#4772](https://github.com/netbox-community/netbox/issues/4772) - Fix "brief" format for the secrets REST API endpoint +* [#4775](https://github.com/netbox-community/netbox/issues/4775) - Allow selecting an alternate device type when creating component templates --- diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index c779f7f98..f3beccc12 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -1026,6 +1026,30 @@ class DeviceTypeFilterForm(BootstrapMixin, CustomFieldFilterForm): # Device component templates # +class ComponentTemplateCreateForm(BootstrapMixin, forms.Form): + """ + Base form for the creation of device component templates. + """ + manufacturer = DynamicModelChoiceField( + queryset=Manufacturer.objects.all(), + required=False, + widget=APISelect( + filter_for={ + 'device_type': 'manufacturer_id' + } + ) + ) + device_type = DynamicModelChoiceField( + queryset=DeviceType.objects.all(), + widget=APISelect( + display_field='model' + ) + ) + name_pattern = ExpandableNameField( + label='Name' + ) + + class ConsolePortTemplateForm(BootstrapMixin, forms.ModelForm): class Meta: @@ -1038,13 +1062,7 @@ class ConsolePortTemplateForm(BootstrapMixin, forms.ModelForm): } -class ConsolePortTemplateCreateForm(BootstrapMixin, forms.Form): - device_type = DynamicModelChoiceField( - queryset=DeviceType.objects.all() - ) - name_pattern = ExpandableNameField( - label='Name' - ) +class ConsolePortTemplateCreateForm(ComponentTemplateCreateForm): type = forms.ChoiceField( choices=add_blank_choice(ConsolePortTypeChoices), widget=StaticSelect2() @@ -1078,13 +1096,7 @@ class ConsoleServerPortTemplateForm(BootstrapMixin, forms.ModelForm): } -class ConsoleServerPortTemplateCreateForm(BootstrapMixin, forms.Form): - device_type = DynamicModelChoiceField( - queryset=DeviceType.objects.all() - ) - name_pattern = ExpandableNameField( - label='Name' - ) +class ConsoleServerPortTemplateCreateForm(ComponentTemplateCreateForm): type = forms.ChoiceField( choices=add_blank_choice(ConsolePortTypeChoices), widget=StaticSelect2() @@ -1118,13 +1130,7 @@ class PowerPortTemplateForm(BootstrapMixin, forms.ModelForm): } -class PowerPortTemplateCreateForm(BootstrapMixin, forms.Form): - device_type = DynamicModelChoiceField( - queryset=DeviceType.objects.all() - ) - name_pattern = ExpandableNameField( - label='Name' - ) +class PowerPortTemplateCreateForm(ComponentTemplateCreateForm): type = forms.ChoiceField( choices=add_blank_choice(PowerPortTypeChoices), required=False @@ -1188,13 +1194,7 @@ class PowerOutletTemplateForm(BootstrapMixin, forms.ModelForm): ) -class PowerOutletTemplateCreateForm(BootstrapMixin, forms.Form): - device_type = DynamicModelChoiceField( - queryset=DeviceType.objects.all() - ) - name_pattern = ExpandableNameField( - label='Name' - ) +class PowerOutletTemplateCreateForm(ComponentTemplateCreateForm): type = forms.ChoiceField( choices=add_blank_choice(PowerOutletTypeChoices), required=False @@ -1275,13 +1275,7 @@ class InterfaceTemplateForm(BootstrapMixin, forms.ModelForm): } -class InterfaceTemplateCreateForm(BootstrapMixin, forms.Form): - device_type = DynamicModelChoiceField( - queryset=DeviceType.objects.all() - ) - name_pattern = ExpandableNameField( - label='Name' - ) +class InterfaceTemplateCreateForm(ComponentTemplateCreateForm): type = forms.ChoiceField( choices=InterfaceTypeChoices, widget=StaticSelect2() @@ -1335,13 +1329,7 @@ class FrontPortTemplateForm(BootstrapMixin, forms.ModelForm): ) -class FrontPortTemplateCreateForm(BootstrapMixin, forms.Form): - device_type = DynamicModelChoiceField( - queryset=DeviceType.objects.all() - ) - name_pattern = ExpandableNameField( - label='Name' - ) +class FrontPortTemplateCreateForm(ComponentTemplateCreateForm): type = forms.ChoiceField( choices=PortTypeChoices, widget=StaticSelect2() @@ -1426,13 +1414,7 @@ class RearPortTemplateForm(BootstrapMixin, forms.ModelForm): } -class RearPortTemplateCreateForm(BootstrapMixin, forms.Form): - device_type = DynamicModelChoiceField( - queryset=DeviceType.objects.all() - ) - name_pattern = ExpandableNameField( - label='Name' - ) +class RearPortTemplateCreateForm(ComponentTemplateCreateForm): type = forms.ChoiceField( choices=PortTypeChoices, widget=StaticSelect2(), @@ -1472,13 +1454,8 @@ class DeviceBayTemplateForm(BootstrapMixin, forms.ModelForm): } -class DeviceBayTemplateCreateForm(BootstrapMixin, forms.Form): - device_type = DynamicModelChoiceField( - queryset=DeviceType.objects.all() - ) - name_pattern = ExpandableNameField( - label='Name' - ) +class DeviceBayTemplateCreateForm(ComponentTemplateCreateForm): + pass # TODO: DeviceBayTemplate has no fields suitable for bulk-editing yet diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index c5964b791..a4ed54b03 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -950,6 +950,10 @@ class ComponentCreateView(GetReturnURLMixin, View): )) if '_addanother' in request.POST: return redirect(request.get_full_path()) + elif 'device_type' in form.cleaned_data: + return redirect(form.cleaned_data['device_type'].get_absolute_url()) + elif 'device' in form.cleaned_data: + return redirect(form.cleaned_data['device'].get_absolute_url()) else: return redirect(self.get_return_url(request))