1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Fixes #2358: Respect custom field default values when creating objects via the REST API

This commit is contained in:
Jeremy Stretch
2019-12-13 14:15:48 -05:00
parent 462cede863
commit a22c7c1539
3 changed files with 59 additions and 5 deletions

View File

@ -8,6 +8,7 @@
## Bug Fixes ## Bug Fixes
* [#2170](https://github.com/netbox-community/netbox/issues/2170) - Prevent the deletion of a virtual chassis when a cross-member LAG is present * [#2170](https://github.com/netbox-community/netbox/issues/2170) - Prevent the deletion of a virtual chassis when a cross-member LAG is present
* [#2358](https://github.com/netbox-community/netbox/issues/2358) - Respect custom field default values when creating objects via the REST API
* [#3749](https://github.com/netbox-community/netbox/issues/3749) - Fix exception on password change page for local users * [#3749](https://github.com/netbox-community/netbox/issues/3749) - Fix exception on password change page for local users
# v2.6.8 (2019-12-10) # v2.6.8 (2019-12-10)

View File

@ -22,7 +22,9 @@ class CustomFieldsSerializer(serializers.BaseSerializer):
def to_internal_value(self, data): def to_internal_value(self, data):
content_type = ContentType.objects.get_for_model(self.parent.Meta.model) content_type = ContentType.objects.get_for_model(self.parent.Meta.model)
custom_fields = {field.name: field for field in CustomField.objects.filter(obj_type=content_type)} custom_fields = {
field.name: field for field in CustomField.objects.filter(obj_type=content_type)
}
for field_name, value in data.items(): for field_name, value in data.items():
@ -107,11 +109,11 @@ class CustomFieldModelSerializer(ValidatedModelSerializer):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if self.instance is not None: # Retrieve the set of CustomFields which apply to this type of object
content_type = ContentType.objects.get_for_model(self.Meta.model)
fields = CustomField.objects.filter(obj_type=content_type)
# Retrieve the set of CustomFields which apply to this type of object if self.instance is not None:
content_type = ContentType.objects.get_for_model(self.Meta.model)
fields = CustomField.objects.filter(obj_type=content_type)
# Populate CustomFieldValues for each instance from database # Populate CustomFieldValues for each instance from database
try: try:
@ -120,6 +122,23 @@ class CustomFieldModelSerializer(ValidatedModelSerializer):
except TypeError: except TypeError:
_populate_custom_fields(self.instance, fields) _populate_custom_fields(self.instance, fields)
else:
# Populate default values
if fields and 'custom_fields' not in self.initial_data:
self.initial_data['custom_fields'] = {}
# Populate initial data using custom field default values
for field in fields:
if field.name not in self.initial_data['custom_fields'] and field.default:
if field.type == CF_TYPE_SELECT:
field_value = field.choices.get(value=field.default).pk
elif field.type == CF_TYPE_BOOLEAN:
field_value = bool(field.default)
else:
field_value = field.default
self.initial_data['custom_fields'][field.name] = field_value
def _save_custom_fields(self, instance, custom_fields): def _save_custom_fields(self, instance, custom_fields):
content_type = ContentType.objects.get_for_model(self.Meta.model) content_type = ContentType.objects.get_for_model(self.Meta.model)
for field_name, value in custom_fields.items(): for field_name, value in custom_fields.items():

View File

@ -301,6 +301,40 @@ class CustomFieldAPITest(APITestCase):
cfv = self.site.custom_field_values.get(field=self.cf_select) cfv = self.site.custom_field_values.get(field=self.cf_select)
self.assertEqual(cfv.value.pk, data['custom_fields']['magic_choice']) self.assertEqual(cfv.value.pk, data['custom_fields']['magic_choice'])
def test_set_custom_field_defaults(self):
"""
Create a new object with no custom field data. Custom field values should be created using the custom fields'
default values.
"""
CUSTOM_FIELD_DEFAULTS = {
'magic_word': 'foobar',
'magic_number': '123',
'is_magic': 'true',
'magic_date': '2019-12-13',
'magic_url': 'http://example.com/',
'magic_choice': self.cf_select_choice1.value,
}
# Update CustomFields to set default values
for field_name, default_value in CUSTOM_FIELD_DEFAULTS.items():
CustomField.objects.filter(name=field_name).update(default=default_value)
data = {
'name': 'Test Site X',
'slug': 'test-site-x',
}
url = reverse('dcim-api:site-list')
response = self.client.post(url, data, format='json', **self.header)
self.assertHttpStatus(response, status.HTTP_201_CREATED)
self.assertEqual(response.data['custom_fields']['magic_word'], CUSTOM_FIELD_DEFAULTS['magic_word'])
self.assertEqual(response.data['custom_fields']['magic_number'], str(CUSTOM_FIELD_DEFAULTS['magic_number']))
self.assertEqual(response.data['custom_fields']['is_magic'], bool(CUSTOM_FIELD_DEFAULTS['is_magic']))
self.assertEqual(response.data['custom_fields']['magic_date'], CUSTOM_FIELD_DEFAULTS['magic_date'])
self.assertEqual(response.data['custom_fields']['magic_url'], CUSTOM_FIELD_DEFAULTS['magic_url'])
self.assertEqual(response.data['custom_fields']['magic_choice'], self.cf_select_choice1.pk)
class CustomFieldChoiceAPITest(APITestCase): class CustomFieldChoiceAPITest(APITestCase):
def setUp(self): def setUp(self):