mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 01:41:22 -06:00
Fixes #6686: Force assignment of null custom field values to objects
This commit is contained in:
parent
5b89cdc868
commit
9b0258fef4
@ -10,6 +10,7 @@
|
||||
### Bug Fixes
|
||||
|
||||
* [#5968](https://github.com/netbox-community/netbox/issues/5968) - Model forms should save empty custom field values as null
|
||||
* [#6686](https://github.com/netbox-community/netbox/issues/6686) - Force assignment of null custom field values to objects
|
||||
|
||||
---
|
||||
|
||||
|
@ -120,17 +120,16 @@ class CustomField(BigIDModel):
|
||||
# Cache instance's original name so we can check later whether it has changed
|
||||
self._name = self.name
|
||||
|
||||
def rename_object_data(self, old_name, new_name):
|
||||
def populate_initial_data(self, content_types):
|
||||
"""
|
||||
Called when a CustomField has been renamed. Updates all assigned object data.
|
||||
Populate initial custom field data upon either a) the creation of a new CustomField, or
|
||||
b) the assignment of an existing CustomField to new object types.
|
||||
"""
|
||||
for ct in self.content_types.all():
|
||||
for ct in content_types:
|
||||
model = ct.model_class()
|
||||
params = {f'custom_field_data__{old_name}__isnull': False}
|
||||
instances = model.objects.filter(**params)
|
||||
for instance in instances:
|
||||
instance.custom_field_data[new_name] = instance.custom_field_data.pop(old_name)
|
||||
model.objects.bulk_update(instances, ['custom_field_data'], batch_size=100)
|
||||
for obj in model.objects.exclude(**{f'custom_field_data__contains': self.name}):
|
||||
obj.custom_field_data[self.name] = self.default
|
||||
obj.save()
|
||||
|
||||
def remove_stale_data(self, content_types):
|
||||
"""
|
||||
@ -143,6 +142,18 @@ class CustomField(BigIDModel):
|
||||
del(obj.custom_field_data[self.name])
|
||||
obj.save()
|
||||
|
||||
def rename_object_data(self, old_name, new_name):
|
||||
"""
|
||||
Called when a CustomField has been renamed. Updates all assigned object data.
|
||||
"""
|
||||
for ct in self.content_types.all():
|
||||
model = ct.model_class()
|
||||
params = {f'custom_field_data__{old_name}__isnull': False}
|
||||
instances = model.objects.filter(**params)
|
||||
for instance in instances:
|
||||
instance.custom_field_data[new_name] = instance.custom_field_data.pop(old_name)
|
||||
model.objects.bulk_update(instances, ['custom_field_data'], batch_size=100)
|
||||
|
||||
def clean(self):
|
||||
super().clean()
|
||||
|
||||
|
@ -108,6 +108,14 @@ def _handle_deleted_object(request, webhook_queue, sender, instance, **kwargs):
|
||||
# Custom fields
|
||||
#
|
||||
|
||||
def handle_cf_added_obj_types(instance, action, pk_set, **kwargs):
|
||||
"""
|
||||
Handle the population of default/null values when a CustomField is added to one or more ContentTypes.
|
||||
"""
|
||||
if action == 'post_add':
|
||||
instance.populate_initial_data(ContentType.objects.filter(pk__in=pk_set))
|
||||
|
||||
|
||||
def handle_cf_removed_obj_types(instance, action, pk_set, **kwargs):
|
||||
"""
|
||||
Handle the cleanup of old custom field data when a CustomField is removed from one or more ContentTypes.
|
||||
@ -131,9 +139,10 @@ def handle_cf_deleted(instance, **kwargs):
|
||||
instance.remove_stale_data(instance.content_types.all())
|
||||
|
||||
|
||||
m2m_changed.connect(handle_cf_removed_obj_types, sender=CustomField.content_types.through)
|
||||
post_save.connect(handle_cf_renamed, sender=CustomField)
|
||||
pre_delete.connect(handle_cf_deleted, sender=CustomField)
|
||||
m2m_changed.connect(handle_cf_added_obj_types, sender=CustomField.content_types.through)
|
||||
m2m_changed.connect(handle_cf_removed_obj_types, sender=CustomField.content_types.through)
|
||||
|
||||
|
||||
#
|
||||
|
@ -42,8 +42,11 @@ class CustomFieldTest(TestCase):
|
||||
cf.save()
|
||||
cf.content_types.set([obj_type])
|
||||
|
||||
# Assign a value to the first Site
|
||||
# Check that the field has a null initial value
|
||||
site = Site.objects.first()
|
||||
self.assertIsNone(site.custom_field_data[cf.name])
|
||||
|
||||
# Assign a value to the first Site
|
||||
site.custom_field_data[cf.name] = data['field_value']
|
||||
site.save()
|
||||
|
||||
@ -73,8 +76,11 @@ class CustomFieldTest(TestCase):
|
||||
cf.save()
|
||||
cf.content_types.set([obj_type])
|
||||
|
||||
# Assign a value to the first Site
|
||||
# Check that the field has a null initial value
|
||||
site = Site.objects.first()
|
||||
self.assertIsNone(site.custom_field_data[cf.name])
|
||||
|
||||
# Assign a value to the first Site
|
||||
site.custom_field_data[cf.name] = 'Option A'
|
||||
site.save()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user