Closes: #471 - selectable on_delete behavior for Object-type fields#485
Conversation
Adds on_delete_behavior field to CustomObjectTypeField (choices: set_null, cascade, protect) that controls what happens to a Custom Object when a referenced object is deleted. Defaults to set_null (preserving the behavior established in PR #484). The choice is enforced via the raw-SQL FK constraint created by _ensure_field_fk_constraint and reflected in the Django field definition. Exposed in forms (single-object fields only), REST API, and migration 0011. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… from POST
CustomObjectTypeFieldForm.__init__ was using self.initial.get("type") to decide
whether to include on_delete_behavior in the form. For POST requests (the final
submission), self.initial is always empty, so field_type evaluated to None,
is_single_object was False, and on_delete_behavior was deleted from the form —
causing it to always save as the default "set_null" regardless of the user's
selection.
Switch to NetBox's get_field_value() utility (same approach used by the parent
CustomFieldForm for the type field itself), which correctly reads from POST data
when the form is bound. Also apply the same fix to the TYPE_MULTIOBJECT unique-
field guard, which had the same self.initial["type"] issue (KeyError for POST).
Add explicit exception logging to _ensure_field_fk_constraint and the
ensure_constraint on_commit closure so failures are visible in logs rather than
silently swallowed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… test failures When a TYPE_OBJECT field is saved, the signal now bumps the related COT's cache_timestamp in the DB so all workers regenerate its model with the correct on_delete behavior. Tests that held Python COT objects across field-creation calls had stale cache_timestamps; add refresh_from_db() before get_model() in those tests so the in-memory timestamp matches the DB value and both code paths resolve to the same model class. New tests in test_deletion.py: - CASCADE and PROTECT on_delete behavior for CO-to-CO FKs - cache_timestamp is bumped when a TYPE_OBJECT field is saved - in-process model cache is cleared when a TYPE_OBJECT field is saved - changing on_delete_behavior re-bumps the related COT's cache_timestamp - non-object fields do not affect unrelated COT timestamps - DB-level ON DELETE RESTRICT is enforced for PROTECT fields (raw SQL) - production code path (get_model_field fresh DB fetch) yields a consistent model class without any caller-side refresh_from_db() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Serializer: return None for on_delete_behavior on non-object-type fields - Model clean(): reject CASCADE/PROTECT for non-object-type fields - Tests: rename set_null test to canonical name; remove alias method Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add two tests that create a PROTECT field, confirm deletion is blocked, change the field to SET_NULL / CASCADE, then confirm deletion succeeds with the expected new behavior. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@claude /review |
|
Claude finished @bctiemann's task in 2m 0s —— View job Code Review — PR #485: Selectable on_delete behavior for Object-type fields
OverviewThis PR adds a user-selectable Issues1. SQL injection via f-string in
|
…d validation - Use connection.ops.quote_name() for all SQL identifiers (no bare f-string interpolation) - Add table_schema = current_schema() filter to information_schema query - clean(): silently reset on_delete_behavior to SET_NULL for non-object fields - serializers: reject on_delete_behavior on non-object fields with a clear API error Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- cot_schema_v1.json: add on_delete_behavior property to object_field - format.py: add on_delete_behavior to FIELD_TYPE_ATTRS["object"] and FIELD_DEFAULTS - exporter.py: export on_delete_behavior when non-default (CASCADE or PROTECT) - comparator.py: detect on_delete_behavior changes in field ALTER diffs - executor.py: apply on_delete_behavior when creating/updating fields via schema - tests: add exporter and comparator coverage for the new attribute Without this, round-tripping a COT with CASCADE/PROTECT fields through export→import would silently convert them all to SET_NULL. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Field Asserts that every field on the model is either wired into the schema pipeline (FIELD_BASE_ATTRS / FIELD_TYPE_ATTRS) or explicitly listed in _SCHEMA_EXCLUDED_ATTRS with a documented reason. This would have caught the on_delete_behavior omission in this PR, and will catch any future field additions that skip the schema pipeline. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Addressed all actionable issues from the review; also noticed that the portable schema needed to be updated to include the new deletion behavior, and at the same time hardened to detect future infrastructural changes to COT/COTF/other internal models. Now has tests to detect such changes. |
|
@arthanson Note that this is based off of another branch that initially fixes the "bug" by setting SET_NULL as the default behavior (a much smaller change). But if you approve this we can merge that into this and then merge both into feature, if we want to simplify the migration path. |
Summary
Extends the fix from #484 by replacing the blanket SET NULL behavior with a user-selectable on_delete_behavior for single-Object-type fields.
Notes
Test plan
Generated with Claude Code