NetBox version
v4.5.7
Feature type
Data model extension
Proposed functionality
Introduce a post_raw_create signal in netbox.signals that is sent after one or more objects of a given model are created using a raw save (i.e. save_base(raw=True)). Unlike Django's built-in post_save, this signal is designed for bulk notification — it receives a pks list rather than a single instance — and is intended for callers that create objects outside the normal model save() path.
The signal follows the same sender-filtering pattern as other Django signals, allowing receivers to subscribe only to the model type they care about:
@receiver(post_raw_create, sender=Cable)
def retrace_cable_paths_after_raw_create(sender, pks, **kwargs):
...
NetBox itself connects a receiver for Cable in dcim/signals.py to retrace cable paths after cables are created this way, since Cable.save() (which fires trace_paths) is bypassed during raw creation.
Use case
Django's save_base(raw=True) is commonly used when restoring or importing serialized object data - for example, during data migrations, fixture loading, or integrations that replay an audit trail of changes. In these scenarios, model-level logic in save() is intentionally skipped to avoid side effects during bulk application.
However, some models (Cable specifically) rely on their save() method to trigger necessary secondary operations. Cable is a concrete example: Cable.save() fires the trace_paths signal, which causes CablePath records to be created or updated. When cables are created via raw save, no CablePath records are produced, leaving the physical connectivity graph incomplete.
Without a hook like post_raw_create, any code that creates objects via raw save must either contain model-specific workarounds or accept that model-level post-save logic will not run. The post_raw_create signal provides a standard extension point: models can register receivers to perform whatever cleanup or secondary operations are needed after raw creation, keeping that logic in the model layer where it belongs rather than in the calling code.
Database changes
N/A
External dependencies
N/A
NetBox version
v4.5.7
Feature type
Data model extension
Proposed functionality
Introduce a post_raw_create signal in netbox.signals that is sent after one or more objects of a given model are created using a raw save (i.e. save_base(raw=True)). Unlike Django's built-in post_save, this signal is designed for bulk notification — it receives a pks list rather than a single instance — and is intended for callers that create objects outside the normal model save() path.
The signal follows the same sender-filtering pattern as other Django signals, allowing receivers to subscribe only to the model type they care about:
NetBox itself connects a receiver for Cable in dcim/signals.py to retrace cable paths after cables are created this way, since Cable.save() (which fires trace_paths) is bypassed during raw creation.
Use case
Django's
save_base(raw=True)is commonly used when restoring or importing serialized object data - for example, during data migrations, fixture loading, or integrations that replay an audit trail of changes. In these scenarios, model-level logic in save() is intentionally skipped to avoid side effects during bulk application.However, some models (Cable specifically) rely on their
save()method to trigger necessary secondary operations. Cable is a concrete example:Cable.save()fires thetrace_paths signal, which causes CablePath records to be created or updated. When cables are created via raw save, no CablePath records are produced, leaving the physical connectivity graph incomplete.Without a hook like post_raw_create, any code that creates objects via raw save must either contain model-specific workarounds or accept that model-level post-save logic will not run. The post_raw_create signal provides a standard extension point: models can register receivers to perform whatever cleanup or secondary operations are needed after raw creation, keeping that logic in the model layer where it belongs rather than in the calling code.
Database changes
N/A
External dependencies
N/A