Jeremy Stretch 7 лет назад
Родитель
Сommit
849db8fe44
3 измененных файлов с 74 добавлено и 13 удалено
  1. 27 8
      netbox/dcim/forms.py
  2. 39 2
      netbox/utilities/forms.py
  3. 8 3
      netbox/utilities/templatetags/helpers.py

+ 27 - 8
netbox/dcim/forms.py

@@ -1764,7 +1764,7 @@ class CableCSVForm(forms.ModelForm):
     side_a_device = FlexibleModelChoiceField(
         queryset=Device.objects.all(),
         to_field_name='name',
-        help_text='Console server name or ID',
+        help_text='Side A device name or ID',
         error_messages={
             'invalid_choice': 'Side A device not found',
         }
@@ -1772,15 +1772,18 @@ class CableCSVForm(forms.ModelForm):
     side_a_type = forms.ModelChoiceField(
         queryset=ContentType.objects.all(),
         limit_choices_to={'model__in': CABLE_TERMINATION_TYPES},
-        to_field_name='model'
+        to_field_name='model',
+        help_text='Side A type'
+    )
+    side_a_name = forms.CharField(
+        help_text='Side A component'
     )
-    side_a_name = forms.CharField()
 
     # Termination B
     side_b_device = FlexibleModelChoiceField(
         queryset=Device.objects.all(),
         to_field_name='name',
-        help_text='Console server name or ID',
+        help_text='Side B device name or ID',
         error_messages={
             'invalid_choice': 'Side B device not found',
         }
@@ -1788,9 +1791,12 @@ class CableCSVForm(forms.ModelForm):
     side_b_type = forms.ModelChoiceField(
         queryset=ContentType.objects.all(),
         limit_choices_to={'model__in': CABLE_TERMINATION_TYPES},
-        to_field_name='model'
+        to_field_name='model',
+        help_text='Side B type'
+    )
+    side_b_name = forms.CharField(
+        help_text='Side B component'
     )
-    side_b_name = forms.CharField()
 
     # Cable attributes
     status = CSVChoiceField(
@@ -1798,13 +1804,26 @@ class CableCSVForm(forms.ModelForm):
         required=False,
         help_text='Connection status'
     )
+    type = CSVChoiceField(
+        choices=CABLE_TYPE_CHOICES,
+        required=False,
+        help_text='Cable type'
+    )
+    length_unit = CSVChoiceField(
+        choices=LENGTH_UNIT_CHOICES,
+        required=False,
+        help_text='Length unit'
+    )
 
     class Meta:
         model = Cable
         fields = [
-            'side_a_device', 'side_a_type', 'side_a_name', 'side_b_device', 'side_b_type', 'side_b_name', 'status',
-            'label',
+            'side_a_device', 'side_a_type', 'side_a_name', 'side_b_device', 'side_b_type', 'side_b_name', 'type',
+            'status', 'label', 'color', 'length', 'length_unit',
         ]
+        help_texts = {
+            'color': 'RGB color in hexadecimal (e.g. 00ff00)'
+        }
 
     # TODO: Merge the clean() methods for either end
     def clean_side_a_name(self):

+ 39 - 2
netbox/utilities/forms.py

@@ -149,6 +149,43 @@ def add_blank_choice(choices):
     return ((None, '---------'),) + tuple(choices)
 
 
+def unpack_grouped_choices(choices):
+    """
+    Unpack a grouped choices hierarchy into a flat list of two-tuples. For example:
+
+    choices = (
+        ('Foo', (
+            (1, 'A'),
+            (2, 'B')
+        )),
+        ('Bar', (
+            (3, 'C'),
+            (4, 'D')
+        ))
+    )
+
+    becomes:
+
+    choices = (
+        (1, 'A'),
+        (2, 'B'),
+        (3, 'C'),
+        (4, 'D')
+    )
+    """
+    unpacked_choices = []
+    for key, value in choices:
+        if key == 1300:
+            breakme = True
+        if isinstance(value, (list, tuple)):
+            # Entered an optgroup
+            for optgroup_key, optgroup_value in value:
+                unpacked_choices.append((optgroup_key, optgroup_value))
+        else:
+            unpacked_choices.append((key, value))
+    return unpacked_choices
+
+
 def utf8_encoder(data):
     for line in data:
         yield line.encode('utf-8')
@@ -353,8 +390,8 @@ class CSVChoiceField(forms.ChoiceField):
 
     def __init__(self, choices, *args, **kwargs):
         super(CSVChoiceField, self).__init__(choices=choices, *args, **kwargs)
-        self.choices = [(label, label) for value, label in choices]
-        self.choice_values = {label: value for value, label in choices}
+        self.choices = [(label, label) for value, label in unpack_grouped_choices(choices)]
+        self.choice_values = {label: value for value, label in unpack_grouped_choices(choices)}
 
     def clean(self, value):
         value = super(CSVChoiceField, self).clean(value)

+ 8 - 3
netbox/utilities/templatetags/helpers.py

@@ -5,6 +5,9 @@ from django import template
 from django.utils.safestring import mark_safe
 from markdown import markdown
 
+from utilities.forms import unpack_grouped_choices
+
+
 register = template.Library()
 
 
@@ -113,14 +116,16 @@ def example_choices(field, arg=3):
     """
     examples = []
     if hasattr(field, 'queryset'):
-        choices = [(obj.pk, getattr(obj, field.to_field_name)) for obj in field.queryset[:arg + 1]]
+        choices = [
+            (obj.pk, getattr(obj, field.to_field_name)) for obj in field.queryset[:arg + 1]
+        ]
     else:
         choices = field.choices
-    for id, label in choices:
+    for value, label in unpack_grouped_choices(choices):
         if len(examples) == arg:
             examples.append('etc.')
             break
-        if not id or not label:
+        if not value or not label:
             continue
         examples.append(label)
     return ', '.join(examples) or 'None'