Просмотр исходного кода

Restore front port component creation

jeremystretch 4 лет назад
Родитель
Сommit
4075cc8518

+ 0 - 1
netbox/dcim/forms/models.py

@@ -1267,7 +1267,6 @@ class InterfaceForm(InterfaceCommonForm, CustomFieldModelForm):
 class FrontPortForm(CustomFieldModelForm):
     rear_port = DynamicModelChoiceField(
         queryset=RearPort.objects.all(),
-        required=False,
         query_params={
             'device_id': '$device',
         }

+ 93 - 0
netbox/dcim/forms/object_create.py

@@ -9,6 +9,8 @@ from utilities.forms import (
 
 __all__ = (
     'ComponentCreateForm',
+    'FrontPortCreateForm',
+    'FrontPortTemplateCreateForm',
     'VirtualChassisCreateForm',
 )
 
@@ -41,6 +43,97 @@ class ComponentCreateForm(BootstrapMixin, forms.Form):
                 }, code='label_pattern_mismatch')
 
 
+class FrontPortTemplateCreateForm(ComponentCreateForm):
+    rear_port_set = forms.MultipleChoiceField(
+        choices=[],
+        label='Rear ports',
+        help_text='Select one rear port assignment for each front port being created.',
+    )
+    field_order = (
+        'name_pattern', 'label_pattern', 'rear_port_set',
+    )
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+        device_type = DeviceType.objects.get(
+            pk=self.initial.get('device_type') or self.data.get('device_type')
+        )
+
+        # Determine which rear port positions are occupied. These will be excluded from the list of available mappings.
+        occupied_port_positions = [
+            (front_port.rear_port_id, front_port.rear_port_position)
+            for front_port in device_type.frontporttemplates.all()
+        ]
+
+        # Populate rear port choices
+        choices = []
+        rear_ports = RearPortTemplate.objects.filter(device_type=device_type)
+        for rear_port in rear_ports:
+            for i in range(1, rear_port.positions + 1):
+                if (rear_port.pk, i) not in occupied_port_positions:
+                    choices.append(
+                        ('{}:{}'.format(rear_port.pk, i), '{}:{}'.format(rear_port.name, i))
+                    )
+        self.fields['rear_port_set'].choices = choices
+
+    def get_iterative_data(self, iteration):
+
+        # Assign rear port and position from selected set
+        rear_port, position = self.cleaned_data['rear_port_set'][iteration].split(':')
+
+        return {
+            'rear_port': int(rear_port),
+            'rear_port_position': int(position),
+        }
+
+
+class FrontPortCreateForm(ComponentCreateForm):
+    rear_port_set = forms.MultipleChoiceField(
+        choices=[],
+        label='Rear ports',
+        help_text='Select one rear port assignment for each front port being created.',
+    )
+    field_order = (
+        'name_pattern', 'label_pattern', 'rear_port_set',
+    )
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+        device = Device.objects.get(
+            pk=self.initial.get('device') or self.data.get('device')
+        )
+
+        # Determine which rear port positions are occupied. These will be excluded from the list of available
+        # mappings.
+        occupied_port_positions = [
+            (front_port.rear_port_id, front_port.rear_port_position)
+            for front_port in device.frontports.all()
+        ]
+
+        # Populate rear port choices
+        choices = []
+        rear_ports = RearPort.objects.filter(device=device)
+        for rear_port in rear_ports:
+            for i in range(1, rear_port.positions + 1):
+                if (rear_port.pk, i) not in occupied_port_positions:
+                    choices.append(
+                        ('{}:{}'.format(rear_port.pk, i), '{}:{}'.format(rear_port.name, i))
+                    )
+        self.fields['rear_port_set'].choices = choices
+
+    def get_iterative_data(self, iteration):
+
+        # Assign rear port and position from selected set
+        rear_port, position = self.cleaned_data['rear_port_set'][iteration].split(':')
+
+        return {
+            'rear_port': int(rear_port),
+            'rear_port_position': int(position),
+        }
+
+
 class VirtualChassisCreateForm(CustomFieldModelForm):
     region = DynamicModelChoiceField(
         queryset=Region.objects.all(),

+ 18 - 0
netbox/dcim/views.py

@@ -1219,8 +1219,17 @@ class InterfaceTemplateBulkDeleteView(generic.BulkDeleteView):
 
 class FrontPortTemplateCreateView(generic.ComponentCreateView):
     queryset = FrontPortTemplate.objects.all()
+    form = forms.FrontPortTemplateCreateForm
     model_form = forms.FrontPortTemplateForm
 
+    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):
     queryset = FrontPortTemplate.objects.all()
@@ -2085,8 +2094,17 @@ class FrontPortView(generic.ObjectView):
 
 class FrontPortCreateView(generic.ComponentCreateView):
     queryset = FrontPort.objects.all()
+    form = forms.FrontPortCreateForm
     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):
     queryset = FrontPort.objects.all()

+ 2 - 3
netbox/netbox/views/generic/object_views.py

@@ -735,7 +735,6 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
         Validate form values and set errors on the form object as they are detected. If
         no errors are found, signal success messages.
         """
-
         logger = logging.getLogger('netbox.views.ComponentCreateView')
         if form.is_valid():
             new_components = []
@@ -749,8 +748,8 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
                 data['name'] = name
                 data['label'] = label
 
-                # if hasattr(form, 'get_iterative_data'):
-                #     data.update(form.get_iterative_data(i))
+                if hasattr(form, 'get_iterative_data'):
+                    data.update(form.get_iterative_data(i))
 
                 component_form = self.model_form(data)
 

+ 5 - 3
netbox/templates/generic/object_edit.html

@@ -31,13 +31,15 @@
 
       <form action="" method="post" enctype="multipart/form-data" class="form-object-edit">
         {% csrf_token %}
-        {% for field in form.hidden_fields %}
-          {{ field }}
-        {% endfor %}
 
         {% block form %}
           {% if form.Meta.fieldsets %}
 
+            {# Render hidden fields #}
+            {% for field in form.hidden_fields %}
+              {{ field }}
+            {% endfor %}
+
             {# Render grouped fields according to Form #}
             {% for group, fields in form.Meta.fieldsets %}
               <div class="field-group mb-5">