Skip to content

Commit

Permalink
Clean up stale data when a custom field is changed/deleted
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremystretch committed Sep 16, 2020
1 parent a743102 commit 2d56a65
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 1 deletion.
11 changes: 11 additions & 0 deletions netbox/extras/models/customfields.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,17 @@ class Meta:
def __str__(self):
return self.label or self.name.replace('_', ' ').capitalize()

def remove_stale_data(self, content_types):
"""
Delete custom field data which is no longer relevant (either because the CustomField is
no longer assigned to a model, or because it has been deleted).
"""
for ct in content_types:
model = ct.model_class()
for obj in model.objects.filter(**{f'custom_field_data__{self.name}__isnull': False}):
del(obj.custom_field_data[self.name])
obj.save()

def clean(self):
# Choices can be set only on selection fields
if self.choices and self.type != CustomFieldTypeChoices.TYPE_SELECT:
Expand Down
27 changes: 26 additions & 1 deletion netbox/extras/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@

from cacheops.signals import cache_invalidated, cache_read
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.db.models.signals import m2m_changed, pre_delete
from django.utils import timezone
from django_prometheus.models import model_deletes, model_inserts, model_updates
from prometheus_client import Counter

from .choices import ObjectChangeActionChoices
from .models import ObjectChange
from .models import CustomField, ObjectChange
from .webhooks import enqueue_webhooks


Expand Down Expand Up @@ -71,6 +73,29 @@ def _handle_deleted_object(request, sender, instance, **kwargs):
model_deletes.labels(instance._meta.model_name).inc()


#
# Custom fields
#

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.
"""
if action == 'post_remove':
instance.remove_stale_data(ContentType.objects.filter(pk__in=pk_set))


def handle_cf_deleted(instance, **kwargs):
"""
Handle the cleanup of old custom field data when a CustomField is deleted.
"""
instance.remove_stale_data(instance.obj_type.all())


m2m_changed.connect(handle_cf_removed_obj_types, sender=CustomField.obj_type.through)
pre_delete.connect(handle_cf_deleted, sender=CustomField)


#
# Caching
#
Expand Down

0 comments on commit 2d56a65

Please sign in to comment.