فهرست منبع

#5306: Introduce CSVContentTypeField for cable termination types

Jeremy Stretch 5 سال پیش
والد
کامیت
cadba74b1f
3فایلهای تغییر یافته به همراه24 افزوده شده و 12 حذف شده
  1. 6 7
      netbox/dcim/forms.py
  2. 3 3
      netbox/dcim/tests/test_views.py
  3. 15 2
      netbox/utilities/forms/fields.py

+ 6 - 7
netbox/dcim/forms.py

@@ -22,9 +22,10 @@ from tenancy.forms import TenancyFilterForm, TenancyForm
 from tenancy.models import Tenant, TenantGroup
 from utilities.forms import (
     APISelect, add_blank_choice, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect,
-    ColorSelect, CommentField, CSVChoiceField, CSVModelChoiceField, CSVModelForm, DynamicModelChoiceField,
-    DynamicModelMultipleChoiceField, ExpandableNameField, form_from_model, JSONField, NumericArrayField, SelectWithPK,
-    SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES,
+    ColorSelect, CommentField, CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, CSVModelForm,
+    DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableNameField, form_from_model, JSONField,
+    NumericArrayField, SelectWithPK, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField,
+    BOOLEAN_WITH_BLANK_CHOICES,
 )
 from virtualization.models import Cluster, ClusterGroup
 from .choices import *
@@ -3758,10 +3759,9 @@ class CableCSVForm(CSVModelForm):
         to_field_name='name',
         help_text='Side A device'
     )
-    side_a_type = CSVModelChoiceField(
+    side_a_type = CSVContentTypeField(
         queryset=ContentType.objects.all(),
         limit_choices_to=CABLE_TERMINATION_MODELS,
-        to_field_name='model',
         help_text='Side A type'
     )
     side_a_name = forms.CharField(
@@ -3774,10 +3774,9 @@ class CableCSVForm(CSVModelForm):
         to_field_name='name',
         help_text='Side B device'
     )
-    side_b_type = CSVModelChoiceField(
+    side_b_type = CSVContentTypeField(
         queryset=ContentType.objects.all(),
         limit_choices_to=CABLE_TERMINATION_MODELS,
-        to_field_name='model',
         help_text='Side B type'
     )
     side_b_name = forms.CharField(

+ 3 - 3
netbox/dcim/tests/test_views.py

@@ -1668,9 +1668,9 @@ class CableTestCase(
 
         cls.csv_data = (
             "side_a_device,side_a_type,side_a_name,side_b_device,side_b_type,side_b_name",
-            "Device 3,interface,Interface 1,Device 4,interface,Interface 1",
-            "Device 3,interface,Interface 2,Device 4,interface,Interface 2",
-            "Device 3,interface,Interface 3,Device 4,interface,Interface 3",
+            "Device 3,dcim.interface,Interface 1,Device 4,dcim.interface,Interface 1",
+            "Device 3,dcim.interface,Interface 2,Device 4,dcim.interface,Interface 2",
+            "Device 3,dcim.interface,Interface 3,Device 4,dcim.interface,Interface 3",
         )
 
         cls.bulk_edit_data = {

+ 15 - 2
netbox/utilities/forms/fields.py

@@ -6,12 +6,11 @@ from io import StringIO
 import django_filters
 from django import forms
 from django.forms.fields import JSONField as _JSONField, InvalidJSONInput
-from django.core.exceptions import MultipleObjectsReturned
+from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
 from django.db.models import Count
 from django.forms import BoundField
 from django.urls import reverse
 
-from utilities.api import get_serializer_for_model
 from utilities.choices import unpack_grouped_choices
 from utilities.validators import EnhancedURLValidator
 from . import widgets
@@ -21,6 +20,7 @@ from .utils import expand_alphanumeric_pattern, expand_ipaddress_pattern
 __all__ = (
     'CommentField',
     'CSVChoiceField',
+    'CSVContentTypeField',
     'CSVDataField',
     'CSVModelChoiceField',
     'DynamicModelChoiceField',
@@ -141,6 +141,19 @@ class CSVModelChoiceField(forms.ModelChoiceField):
             )
 
 
+class CSVContentTypeField(CSVModelChoiceField):
+
+    def to_python(self, value):
+        try:
+            app_label, model = value.split('.')
+        except ValueError:
+            raise forms.ValidationError(f'Object type must be specified as "<app>.<model>"')
+        try:
+            return self.queryset.get(app_label=app_label, model=model)
+        except ObjectDoesNotExist:
+            raise forms.ValidationError(f'Invalid object type')
+
+
 class ExpandableNameField(forms.CharField):
     """
     A field which allows for numeric range expansion