mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
59 lines
2.0 KiB
Python
59 lines
2.0 KiB
Python
import logging
|
|
|
|
from django.db.models.signals import post_save
|
|
from django.dispatch import receiver
|
|
|
|
from netbox.registry import registry
|
|
|
|
|
|
logger = logging.getLogger('netbox.denormalized')
|
|
|
|
|
|
def register(model, field_name, mappings):
|
|
"""
|
|
Register a denormalized model field to ensure that it is kept up-to-date with the related object.
|
|
|
|
Args:
|
|
model: The class being updated
|
|
field_name: The name of the field related to the triggering instance
|
|
mappings: Dictionary mapping of local to remote fields
|
|
"""
|
|
logger.debug(f'Registering denormalized field {model}.{field_name}')
|
|
|
|
field = model._meta.get_field(field_name)
|
|
rel_model = field.related_model
|
|
|
|
registry['denormalized_fields'][rel_model].append(
|
|
(model, field_name, mappings)
|
|
)
|
|
|
|
|
|
@receiver(post_save)
|
|
def update_denormalized_fields(sender, instance, created, raw, **kwargs):
|
|
"""
|
|
Check if the sender has denormalized fields registered, and update them as necessary.
|
|
"""
|
|
def _get_field_value(instance, field_name):
|
|
field = instance._meta.get_field(field_name)
|
|
return field.value_from_object(instance)
|
|
|
|
# Skip for new objects or those being populated from raw data
|
|
if created or raw:
|
|
return
|
|
|
|
# Look up any denormalized fields referencing this model from the application registry
|
|
for model, field_name, mappings in registry['denormalized_fields'].get(sender, []):
|
|
logger.debug(f'Updating denormalized values for {model}.{field_name}')
|
|
filter_params = {
|
|
field_name: instance.pk,
|
|
}
|
|
update_params = {
|
|
# Map the denormalized field names to the instance's values
|
|
denorm: _get_field_value(instance, origin) for denorm, origin in mappings.items()
|
|
}
|
|
|
|
# TODO: Improve efficiency here by placing conditions on the query?
|
|
# Update all the denormalized fields with the triggering object's new values
|
|
count = model.objects.filter(**filter_params).update(**update_params)
|
|
logger.debug(f'Updated {count} rows')
|