Rename the 'results' key to 'errors' and omit successful objects from
the bulk create/update/destroy error response, applied consistently
across all three mixins. len(errors) replaces the separate error_count
bookkeeping. Also change the ProtectedError/RestrictedError entry's
'detail' key to '__all__' to match the field-based error format used
by creates and updates, and correct a comment that implied bulk delete
enforces a permission boundary the single-object delete endpoint
doesn't actually have.
Addresses review feedback from @jeremystretch.
Expose an event's prechange and postchange snapshots to event rule
condition evaluation, making snapshots.prechange.<attr> and
snapshots.postchange.<attr> available through the existing dot-path
syntax.
Add changed and unchanged snapshot operators for comparing an attribute
across the two snapshots without requiring a condition value. These
operators support rules such as firing only when a field transitions to a
specific state.
Make condition values optional only for snapshot operators by introducing
a missing-value sentinel, while preserving value requirements for all
other operators. Reject invalid combinations such as using changed or
unchanged with an explicit value or with an attr starting with snapshots.
Fail closed when condition paths traverse invalid snapshot structures,
including raw scalar snapshot values such as status strings, by treating
unresolvable snapshot-operator paths as missing and converting invalid
direct paths to InvalidCondition.
Document the new snapshot path syntax, changed and unchanged operators,
create/delete snapshot behavior, and the serialization differences
between snapshot data and REST API data. Add regression and integration
tests covering validation, transition behavior, null snapshot edge cases,
direct snapshot paths, and event rule evaluation.
Enable comma-separated Device, Power Panel, and Termination name lists
in Cable CSV/JSON/YAML imports. Each side accepts either one parent for
all terminations or one parent per name, preserving submission order for
connector assignment.
Add validation for duplicate terminations, empty names, parent count
mismatches, and MultipleObjectsReturned cases. Change side_a/b_device
and side_a/b_power_panel fields from CSVModelChoiceField to
CSVModelMultipleChoiceField with updated help text.
Fixes#18645
Success is now inferred from the absence of an errors key, matching
Jeremy's suggestion. Error entries carry only {id/index, errors};
successful entries carry only {id/index}. Update all tests accordingly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move single-object create back inside transaction.atomic() (comment 1)
- Replace repeated result-list iterations with local error_count counters
in create(), perform_bulk_update(), and perform_bulk_destroy() (comments 3, 4, 6)
- Rewrite perform_bulk_update() from two-pass (validate-all, save-all) to
sequential per-object validate+save, matching SequentialBulkCreatesMixin;
subsequent validators now see DB state from prior saves so cross-object
uniqueness conflicts are caught at validation time (comment 5)
- Update bulk_update() and bulk_destroy() callers to unpack new return tuples
and use the counters directly
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Security: remove object names/PKs from ProtectedError detail; report count only
to avoid exposing objects the caller may lack permission to view
- i18n: wrap new error detail strings with _().format() to match codebase convention
- Redundancy: remove superfluous `results and` guard in bulk_destroy (any() on an
empty list already returns False)
- Comment: explain that SequentialBulkCreatesMixin continues provisionally creating
after a failure so cross-object validators see a realistic state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use a valid first item (create_data[0]) alongside an invalid second item ({})
so the test exercises both the 'ok' result shape and the atomic rollback of an
item that would otherwise have been persisted.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use pre-captured `pk` consistently in perform_bulk_destroy error path
- Add comment clarifying the `if results:` sentinel in bulk_update
- Add per-field atomicity assertion to test_bulk_update_objects_validation_error
- Use ID-keyed dict instead of positional index in test_bulk_delete_objects_protected
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bulk update (PATCH), sequential bulk create (POST), and bulk delete (DELETE) on
list endpoints now collect per-object errors instead of aborting on the first
failure. When any objects fail, the entire operation is rolled back atomically
and a 400/409 response is returned with a structured payload:
{
"detail": "1 of 3 objects failed validation.",
"results": [
{"id": 1, "status": "ok"},
{"id": 2, "status": "error", "errors": {"name": ["..."]}},
{"id": 3, "status": "ok"}
]
}
For bulk creates via SequentialBulkCreatesMixin the correlator is "index"
(zero-based position in the request list) since no IDs exist yet. For bulk
delete the status code remains 409 and the correlator is "id".
Successful operations are unchanged (200/201/204).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Only display the saved filter dropdown in table controls when a filter
form is present and includes a filter_id field. This prevents rendering
an empty or non-functional dropdown when saved filters are unavailable.
Render navigation menu buttons with the secondary ghost style when their
color is unset or set to the default choice.
This fixes plugin menu buttons, which default to "default" rather than
None, while preserving explicitly configured button colors.
Replace the grouped button wrapper with a semantic
`dropdown-item-buttons` container and render sidebar action buttons with
the `btn-ghost` style while preserving existing color support.
Scope dropdown item link styles to direct child anchors so nested action
buttons keep their intended styling, and reveal the buttons on hover,
active, and focus-within states.
* refactor(forms): Add GenericObjectChoiceField
Replace separate scope_type/scope and parent_object_type/parent field
pairs with unified GenericObjectChoiceField. Introduce
GenericObjectFormMixin to handle GFK descriptor initialization and
assignment.
This removes redundant HTMX/queryset setup logic from ScopedForm,
VLANGroupForm, and ServiceForm by delegating GFK presentation to a
single reusable field and mixin pair. Field query param references now
use `$scope_object_id` instead of `$scope` to match the subwidget name.
Fixes#19821
* fix(forms): Skip validation on HTMX bulk-edit dependent field refresh
Render bulk-edit form unbound when an HTMX request changes a dependent
field (e.g. content type) without clicking Apply. This prevents
validation errors from surfacing before the user submits.
Cache ContentType lookups in GenericObjectChoiceField and sync widget
references before setting queryset to ensure choices land on the
rendered subwidget.
* fix(ipam): Update scope query params for GenericObjectChoiceField
Change available-prefix Add links to use `scope_content_type` and
`scope_object_id` query parameters instead of `scope_type` and `scope`.
This aligns with the GenericObjectChoiceField subwidget naming
introduced in the earlier refactor.
* refactor(models): Simplify GFK handling in clone_fields
Replace `scope_type`/`scope_id` pairs with bare `scope` GFK names in
clone_fields across models. Update CloningMixin to emit GFK subwidget
parameters (`scope_content_type`, `scope_object_id`) directly when a
GenericForeignKey appears in clone_fields.
* Update pre-populated links
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
Move the device/VM lookup ahead of is_primary/is_oob handling and only
process those flags when a parent device or VM exists.
This avoids dereferencing None for explicit falsy CSV values such as
"false", which are not covered by the column-absent checks in
clean_is_primary() and clean_is_oob(). This also keeps the behavior
aligned with MACAddressImportForm.
Reject duplicate ScriptModule uploads before writing to storage to
prevent failed uploads from corrupting existing files. Add existence
check in cleanup path to avoid deleting files referenced by concurrent
uploads that won the race.
Fixes#22543
Introduce Breakout1C8Px8C1PCableProfile to map a single 8-position
connector to eight single-position connectors. Add profile choice,
registration, and bidirectional link peer tests for the new breakout.
Fixes#22279