diff --git a/docs/release-notes/version-3.4.md b/docs/release-notes/version-3.4.md index ce3edc07c..d6b26c4eb 100644 --- a/docs/release-notes/version-3.4.md +++ b/docs/release-notes/version-3.4.md @@ -17,6 +17,10 @@ NetBox's global search functionality has been completely overhauled and replaced by a new cache-based lookup. +### JSON/YAML Bulk Imports ([#4347](https://github.com/netbox-community/netbox/issues/4347)) + +NetBox's bulk import feature, which was previously limited to CSV-formatted data for most objects, has been extended to support the import of objects from JSON and/or YAML data as well. + #### CSV-Based Bulk Updates ([#7961](https://github.com/netbox-community/netbox/issues/7961)) NetBox's CSV-based bulk import functionality has been extended to support also modifying existing objects. When an `id` column is present in the import form, it will be used to infer the object to be modified, rather than a new object being created. All fields (columns) are optional when modifying existing objects. diff --git a/netbox/netbox/views/generic/bulk_views.py b/netbox/netbox/views/generic/bulk_views.py index 1a83c9de2..86ffbf224 100644 --- a/netbox/netbox/views/generic/bulk_views.py +++ b/netbox/netbox/views/generic/bulk_views.py @@ -375,19 +375,14 @@ class BulkImportView(GetReturnURLMixin, BaseMultiObjectView): form.add_error('data', f"Row {i}: Object with ID {object_id} does not exist") raise ValidationError('') + # Instantiate the model form for the object + model_form_kwargs = { + 'data': record, + 'instance': instance, + } if form.cleaned_data['format'] == ImportFormatChoices.CSV: - model_form = self.model_form(record, instance=instance, headers=form._csv_headers) - else: - model_form = self.model_form(record, instance=instance) - # Assign default values for any fields which were not specified. - # We have to do this manually because passing 'initial=' to the form - # on initialization merely sets default values for the widgets. - # Since widgets are not used for YAML/JSON import, we first bind the - # imported data normally, then update the form's data with the applicable - # field defaults as needed prior to form validation. - for field_name, field in model_form.fields.items(): - if field_name not in record and hasattr(field, 'initial'): - model_form.data[field_name] = field.initial + model_form_kwargs['headers'] = form._csv_headers + model_form = self.model_form(**model_form_kwargs) # When updating, omit all form fields other than those specified in the record. (No # fields are required when modifying an existing object.)