Explorar el Código

16073 set default custom fields on CSV import (#17152)

* 16073 set default custom fields on CSV import

* 16073 add test case

* Remove second for loop

---------

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
Arthur Hanson hace 1 año
padre
commit
872af72b8e
Se han modificado 2 ficheros con 40 adiciones y 1 borrados
  1. 26 0
      netbox/netbox/tests/test_import.py
  2. 14 1
      netbox/netbox/views/generic/bulk_views.py

+ 26 - 0
netbox/netbox/tests/test_import.py

@@ -2,6 +2,7 @@ from django.test import override_settings
 
 from core.models import ObjectType
 from dcim.models import *
+from extras.models import CustomField
 from netbox.choices import CSVDelimiterChoices, ImportFormatChoices
 from users.models import ObjectPermission
 from utilities.testing import ModelViewTestCase, create_tags
@@ -116,3 +117,28 @@ class CSVImportTestCase(ModelViewTestCase):
         # Test POST with permission
         self.assertHttpStatus(self.client.post(self._get_url('import'), data), 200)
         self.assertEqual(Region.objects.count(), 0)
+
+    @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
+    def test_custom_field_defaults(self):
+        self.add_permissions('dcim.add_region')
+        csv_data = [
+            'name,slug,description',
+            'Region 1,region-1,abc',
+        ]
+        data = {
+            'format': ImportFormatChoices.CSV,
+            'data': self._get_csv_data(csv_data),
+            'csv_delimiter': CSVDelimiterChoices.AUTO,
+        }
+
+        cf = CustomField.objects.create(
+            name='tcf',
+            type='text',
+            required=False,
+            default='def-cf-text'
+        )
+        cf.object_types.set([ObjectType.objects.get_for_model(self.model)])
+
+        self.assertHttpStatus(self.client.post(self._get_url('import'), data), 302)
+        region = Region.objects.get(slug='region-1')
+        self.assertEqual(region.cf['tcf'], 'def-cf-text')

+ 14 - 1
netbox/netbox/views/generic/bulk_views.py

@@ -4,6 +4,7 @@ from copy import deepcopy
 
 from django.contrib import messages
 from django.contrib.contenttypes.fields import GenericRel
+from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist, ValidationError
 from django.db import transaction, IntegrityError
 from django.db.models import ManyToManyField, ProtectedError, RestrictedError
@@ -17,7 +18,8 @@ from django.utils.translation import gettext as _
 from django_tables2.export import TableExport
 
 from core.models import ObjectType
-from extras.models import ExportTemplate
+from extras.choices import CustomFieldUIEditableChoices
+from extras.models import CustomField, ExportTemplate
 from extras.signals import clear_events
 from utilities.error_handlers import handle_protectederror
 from utilities.exceptions import AbortRequest, AbortTransaction, PermissionsViolation
@@ -415,6 +417,17 @@ class BulkImportView(GetReturnURLMixin, BaseMultiObjectView):
                 if instance.pk and hasattr(instance, 'snapshot'):
                     instance.snapshot()
 
+            else:
+                # For newly created objects, apply any default custom field values
+                custom_fields = CustomField.objects.filter(
+                    object_types=ContentType.objects.get_for_model(self.queryset.model),
+                    ui_editable=CustomFieldUIEditableChoices.YES
+                )
+                for cf in custom_fields:
+                    field_name = f'cf_{cf.name}'
+                    if field_name not in record:
+                        record[field_name] = cf.default
+
             # Instantiate the model form for the object
             model_form_kwargs = {
                 'data': record,