Cable.save() recomputed _abs_length in memory but never added it to
update_fields, so a save naming length or length_unit left the stored
normalized value stale. Derive it from the values the row will hold
after the save and persist it alongside its source fields.
Fixes#23096
Add FILTER_ARRAY_BASED_LOOKUP_MAP to maintain 'contains' lookup under
negation for MultiValueArrayFilter, preventing fallback to exact match.
Negation now correctly excludes objects whose array contains the value
rather than matching it exactly.
Fixes#23117
Validate REST script input before enqueueing jobs. Resolve ObjectVar
IDs to model instances and MultiObjectVar IDs to querysets, returning
HTTP 400 with errors nested under data when validation fails.
Share form preparation between the API and UI, including multi-value
defaults, while keeping validation out of the job runner to preserve
other execution paths. Exclude only known execution fields from script
data and prevent _notifications from leaking into CLI script input.
Document the REST compatibility changes, including required-field
validation and discarded undeclared keys. Add regression coverage for
object resolution, defaults, validation errors, and execution options.
Co-authored-by: Martin Burggraf <martin.burggraf@netclusive.com>
* fix(dcim): Prevent path rebuild when Cable Terminations unchanged
Compare Cable Terminations against stored values instead of the empty
cache when checking for modifications, so a freshly loaded Cable that is
resaved with the same terminations no longer rebuilds its paths. Raise
the flag whenever update_terminations() force-recreates an end, since
the edit form warms the cache that gated it and a profile change then
tore every path down without rebuilding it. Add regression tests for
both.
Fixes#23097
* fix(dcim): Preserve cable end order when terminations unchanged
Compare cable terminations against stored values instead of potentially
stale prefetched relations when checking for modifications. Skip setting
terminations in the form's clean() when a saved cable's members are
unchanged, preserving the connector order assigned by the profile.
Does two things:
1. Adds a regression test to ensure that the `extras_scripts_run`
operation is always present in contrib/openapi.json. This has
regressed at least once since original implementation, so I wanted to
make sure we catch it quickly in the future.
2. Overrides the Django `CACHES` setting for the OpenAPISchemaTestCase,
which contains the new test, so that caching of the schema is
disabled. This caused problems by masking whether or not the
regression test (and other existing tests) were failing/succeeding in
response to changes or not.
RQQueueTestMixin cleared RQ queues with FLUSHALL, which empties every
database on the Redis server — including the caching database, whose
'config'/'config_version' keys are shared by all parallel test workers.
A flush landing mid-test forces an unrelated worker to re-read
core_configrevision, adding two queries to the affected request. Flush
only the queue's own database instead.
Also stop GraphQLDeferredColumnTestCase from comparing total query counts
between two requests, which is what surfaced the race as intermittent
"Query count grew from 7 to 9" failures in CI. Assert that the target
table is read exactly once per request instead, as #23034 did for the
equivalent custom fields test.
Set `_terminations_modified` flag when recreating terminations to ensure
paths are rebuilt even when endpoints remain unchanged.
Reset `_orig_status`, `_orig_profile`, and `_terminations_modified`
after saving a cable to prevent repeated saves from recreating
terminations and paths.
Add comprehensive test coverage for profile changes, trunk regrouping,
and mid-span cables.
Validate the effective timeout and notification settings at the
ScriptJob enqueue boundary so invalid script configuration is reported
consistently across all execution paths instead of raising an unhandled
exception.
Preserve the inherited positional enqueue contract and prevent tests
from interfering through shared RQ queue state during parallel runs.
Introduces normalize_update_fields() utility to materialize one-shot
iterables like generators into frozensets, preventing bugs in save()
overrides that perform membership tests. Fixes channelization cascades,
module moves, and ltree parent tracking when using generator
expressions.
Fixes#23074
Recognize Django's ManyToManyRel in get_prefetches_for_serializer().
Because it is a sibling of ManyToOneRel rather than a subclass, reverse
many-to-many accessors were omitted from the generated prefetch paths and
fetched once per serialized object.
Add regression coverage for both automatically generated fields and
SerializedPKRelatedField(many=True), and regenerate the affected ASN and
ObjectPermission API query-count baselines.
Fixes#23060
Introduce `normalize_update_fields()` utility to convert update_fields
to frozenset, preventing one-shot iterables from being consumed during
membership tests. Update Service, VLANGroup, and CircuitTermination
save methods to use normalized fields. Add comprehensive test coverage.
Fixes generator exhaustion when save() overrides check field membership
before persisting denormalized caches alongside their source fields.
Fixes#23078
Move scope assignment before validation to prevent stale scope values
on instances when validation fails. Refactor VLANGroupForm to inherit
from ScopedForm, removing duplicate scope handling code. Add test
coverage for scope type changes and validation errors.
Fixes#23040
Serializers used only in a nested context have no complete form in the schema, so
prefixing them with "Brief" renamed an existing component to no purpose and dropped
the old name entirely. Exempt serializers declaring an explicit Meta.ref_name from
the prefix, and pin the three affected names.
This narrows the schema diff to the fields the bug actually affected: no components
are removed, and the nine which are added are purely additive.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* Drop the non-BaseModelSerializer fallback in FixSerializedPKRelatedField.
SerializedPKRelatedField.to_representation() passes nested unconditionally, so a
serializer which doesn't accept it raises TypeError on every read; the branch
documented a component for a configuration the API cannot serve.
* Generate the OpenAPI schema once per class rather than once per test method.
* Exercise the component.ref and request-schema return paths, and use SimpleTestCase
for the tests which don't touch the database.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
FixSerializedPKRelatedField passed the serializer class to resolve_serializer(),
which instantiates it with no arguments. The field's nested setting was therefore
lost, and the generated response schema referenced the complete component (with
the complete field set) even where the field renders a brief representation.
Resolve an instance carrying the field's nested setting instead. Request schemas
are unaffected and continue to accept integer primary keys.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Teach _get_nested_serializer() to unwrap ManyRelatedField and resolve the
serializer configured on SerializedPKRelatedField. Preserve the field's
nested value so prefetch discovery follows brief_fields for nested
representations and the full field set otherwise.
Guard the recursion against reference cycles by tracking the serializer
states already being resolved on the current path. Because nested defaults
to False the target expands its full field set, so a self-referential or
mutually referential declaration would otherwise recurse without a
termination condition. The key pairs the serializer class with its
effective field set, since re-entering a serializer at a narrower depth is
finite rather than cyclic, and the states are copied per frame so a sibling
field can still expand what another one stops at.
Populate interface VDC relationships and VRF route target assignments in
the API test fixtures, update the two query count baselines, and add
coverage for direct, many-valued and non-nested serialized related fields
alongside self-referential, mutually referential, brief-depth and
sibling-reuse cases.
Fixes#22988
SideNav classified the viewport only during construction. Resizing past
the `lg` breakpoint therefore left the desktop sidebar in its previous
mobile state, and the menu group containing the current page remained
collapsed until the pointer entered the sidebar.
Use the existing desktop media query as an event source. Apply the
persisted pin preference directly to the body attributes during
initialization and on each breakpoint transition, then reinitialize the
active menu section.
Avoid calling `pin()` or `unpin()` during responsive transitions so
Bootstrap retains ownership of its collapse state and the stored
preference is not rewritten unnecessarily.
Also remove the `show` class from a menu group toggle when collapsing
its section to keep the toggle and menu state synchronized.
Fixes#23035
Move owner field from fieldsets to Meta.fields in PowerOutletForm and
add it to ServiceCreateForm Meta.fields. Ensures owner field appears in
forms and can be properly saved. Adds test coverage with Owner creation.
Fixes#23052
Replace NumberFilter with MultiValueNumberFilter for VLANGroup scope
filters (Region, Site Group, Site, Location, Rack Group, Rack,
Cluster Group, Cluster). Update filter_scope method to use `__in`
lookup and add comprehensive test coverage for multi-value filtering.
Fixes#22671