Skip to content

Commit 872af72

Browse files
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 <[email protected]>
1 parent 5a9f9af commit 872af72

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

netbox/netbox/tests/test_import.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from core.models import ObjectType
44
from dcim.models import *
5+
from extras.models import CustomField
56
from netbox.choices import CSVDelimiterChoices, ImportFormatChoices
67
from users.models import ObjectPermission
78
from utilities.testing import ModelViewTestCase, create_tags
@@ -116,3 +117,28 @@ def test_invalid_tags(self):
116117
# Test POST with permission
117118
self.assertHttpStatus(self.client.post(self._get_url('import'), data), 200)
118119
self.assertEqual(Region.objects.count(), 0)
120+
121+
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
122+
def test_custom_field_defaults(self):
123+
self.add_permissions('dcim.add_region')
124+
csv_data = [
125+
'name,slug,description',
126+
'Region 1,region-1,abc',
127+
]
128+
data = {
129+
'format': ImportFormatChoices.CSV,
130+
'data': self._get_csv_data(csv_data),
131+
'csv_delimiter': CSVDelimiterChoices.AUTO,
132+
}
133+
134+
cf = CustomField.objects.create(
135+
name='tcf',
136+
type='text',
137+
required=False,
138+
default='def-cf-text'
139+
)
140+
cf.object_types.set([ObjectType.objects.get_for_model(self.model)])
141+
142+
self.assertHttpStatus(self.client.post(self._get_url('import'), data), 302)
143+
region = Region.objects.get(slug='region-1')
144+
self.assertEqual(region.cf['tcf'], 'def-cf-text')

netbox/netbox/views/generic/bulk_views.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from django.contrib import messages
66
from django.contrib.contenttypes.fields import GenericRel
7+
from django.contrib.contenttypes.models import ContentType
78
from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist, ValidationError
89
from django.db import transaction, IntegrityError
910
from django.db.models import ManyToManyField, ProtectedError, RestrictedError
@@ -17,7 +18,8 @@
1718
from django_tables2.export import TableExport
1819

1920
from core.models import ObjectType
20-
from extras.models import ExportTemplate
21+
from extras.choices import CustomFieldUIEditableChoices
22+
from extras.models import CustomField, ExportTemplate
2123
from extras.signals import clear_events
2224
from utilities.error_handlers import handle_protectederror
2325
from utilities.exceptions import AbortRequest, AbortTransaction, PermissionsViolation
@@ -415,6 +417,17 @@ def create_and_update_objects(self, form, request):
415417
if instance.pk and hasattr(instance, 'snapshot'):
416418
instance.snapshot()
417419

420+
else:
421+
# For newly created objects, apply any default custom field values
422+
custom_fields = CustomField.objects.filter(
423+
object_types=ContentType.objects.get_for_model(self.queryset.model),
424+
ui_editable=CustomFieldUIEditableChoices.YES
425+
)
426+
for cf in custom_fields:
427+
field_name = f'cf_{cf.name}'
428+
if field_name not in record:
429+
record[field_name] = cf.default
430+
418431
# Instantiate the model form for the object
419432
model_form_kwargs = {
420433
'data': record,

0 commit comments

Comments
 (0)