Kaynağa Gözat

Restore front port component creation

jeremystretch 4 yıl önce
ebeveyn
işleme
4075cc8518

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

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

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

@@ -9,6 +9,8 @@ from utilities.forms import (
 
 
 __all__ = (
 __all__ = (
     'ComponentCreateForm',
     'ComponentCreateForm',
+    'FrontPortCreateForm',
+    'FrontPortTemplateCreateForm',
     'VirtualChassisCreateForm',
     'VirtualChassisCreateForm',
 )
 )
 
 
@@ -41,6 +43,97 @@ class ComponentCreateForm(BootstrapMixin, forms.Form):
                 }, code='label_pattern_mismatch')
                 }, 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):
 class VirtualChassisCreateForm(CustomFieldModelForm):
     region = DynamicModelChoiceField(
     region = DynamicModelChoiceField(
         queryset=Region.objects.all(),
         queryset=Region.objects.all(),

+ 18 - 0
netbox/dcim/views.py

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

+ 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
         Validate form values and set errors on the form object as they are detected. If
         no errors are found, signal success messages.
         no errors are found, signal success messages.
         """
         """
-
         logger = logging.getLogger('netbox.views.ComponentCreateView')
         logger = logging.getLogger('netbox.views.ComponentCreateView')
         if form.is_valid():
         if form.is_valid():
             new_components = []
             new_components = []
@@ -749,8 +748,8 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
                 data['name'] = name
                 data['name'] = name
                 data['label'] = label
                 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)
                 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">
       <form action="" method="post" enctype="multipart/form-data" class="form-object-edit">
         {% csrf_token %}
         {% csrf_token %}
-        {% for field in form.hidden_fields %}
-          {{ field }}
-        {% endfor %}
 
 
         {% block form %}
         {% block form %}
           {% if form.Meta.fieldsets %}
           {% if form.Meta.fieldsets %}
 
 
+            {# Render hidden fields #}
+            {% for field in form.hidden_fields %}
+              {{ field }}
+            {% endfor %}
+
             {# Render grouped fields according to Form #}
             {# Render grouped fields according to Form #}
             {% for group, fields in form.Meta.fieldsets %}
             {% for group, fields in form.Meta.fieldsets %}
               <div class="field-group mb-5">
               <div class="field-group mb-5">