Address review feedback on #22253:
- Registry stores resolvers as {app_label: resolver} dict instead of a
flat list, so each app can only register a resolver for its own models.
- register_serializer_resolver() now takes (app_label, resolver) and
get_serializer_for_model() only consults the resolver registered for
the model's own app.
- Remove 'serializer_resolver' from DEFAULT_RESOURCE_PATHS so this niche
resource is loaded only when a plugin explicitly defines it. The
PluginConfig.ready() path imports the configured path directly and
registers it under self.label.
- Update tests for the new per-app scoping; verify a resolver registered
for one app does not affect lookups in another.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add support for literal `{lat}` and `{lon}` placeholders in `MAPS_URL`
when rendering GPS coordinate links. Existing configurations continue to
work by falling back to appending `lat,lon` when no coordinate placeholders
are present.
Move map URL handling into shared UI helpers so `GPSCoordinatesAttr` and
`AddressAttr` use consistent placeholder detection. When `MAPS_URL` contains
coordinate placeholders, suppress address-based map links to avoid rendering
invalid URLs.
Add tests for placeholder replacement, decimal coordinate values, fallback
behavior, and address link suppression. Also document the address link behavior
in the `MAPS_URL` configuration description.
The new "select at least one field" guard fires when rename_fields is set
and no field_names are submitted. Add field_names=['name'] to both the
preview and apply POST data so the test exercises the intended rename path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The `submitted` list comprehension previously called `f in self.rename_fields`
which raises TypeError when a subclass sets rename_fields=None. Short-circuit
with `self.rename_fields and` to safely handle None, empty tuple, and populated
tuples uniformly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add form error when all field checkboxes are unchecked on submit;
previously fell back to renaming every declared field silently
- Remove obj.new_name backward-compat assignment; no template or
documented plugin API references it (all use obj.new_names now)
- Update base test data to include field_names=['name'] so the guard
does not fire in views-framework tests that don't specify fields
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move field checkboxes before the find/replace/use_regex inputs so they
are not visually conflated with the 'use regex' checkbox
- Fix indentation inside the {% if rename_fields %} block
- Add trailing newline to bulk_rename.html
- Add test_bulk_rename_name_and_label_fields to verify that submitting
field_names=['name', 'label'] updates both fields simultaneously
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the dynamic label-field detection (_get_rename_fields) and dropdown
with an explicit rename_fields class attribute and per-field checkboxes:
- BulkRenameView.rename_fields: tuple of field names (e.g. ('name', 'label'))
declared on the view. field_name is retained for backward compatibility
with plugins that set it directly.
- When rename_fields has 2+ entries, the template renders a Bootstrap-styled
checkbox per field (all checked by default) so users can apply the
find/replace to any combination of fields simultaneously. Checkboxes are
rendered directly in the template and read from request.POST rather than
through a form field, to avoid Django widget styling complications.
- _rename_objects accepts field_names (list) and stores per-field results in
obj.new_names (SimpleNamespace) + obj.has_changes for template use.
- The apply step iterates field_names and setattr for each selected field.
- bulk_rename.html: unified table iterates selected_field_names; form section
inline-expands render_form so the Fields checkboxes slot between the
standard fields and the changelog fieldset.
- Add rename_fields = ('name', 'label') to the 20 DCIM component/template
views whose models carry both name and label fields.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Trim _get_rename_fields docstring and required=False comment to single lines
- Pass field_name as a parameter to _rename_objects instead of extracting it
from form.cleaned_data inside the method (single source of truth)
- Fix test skip condition to use _meta.fields instead of _meta.get_fields()
to match the implementation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
For device/module component models, the preview table now always shows four
columns: Current Name, New Name, Current Label, New Label. The New column
for the non-targeted field is left empty to make clear which field the
find/replace pattern applies to. This gives users full context when
identifying objects and planning renames.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use _meta.fields (concrete fields only) instead of _meta.get_fields()
to check for label field presence; avoids iterating reverse relations
- Simplify template column headers via blocktrans + field_name|title
instead of duplicated if/else blocks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Device/module component models (Interface, ConsolePort, FrontPort, etc. and
their template counterparts) have both a 'name' and a 'label' field. The bulk
rename form now shows a 'Field' dropdown on these models so users can choose
which field to apply the find/replace pattern to; the selector is omitted for
models that have only one renameable field.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds warning and examples for validating NetBox objects before saving
in Custom Scripts. Direct ORM writes bypass UI/API validation and can
introduce invalid data. Recommends calling `full_clean()` explicitly.
Fixes#22249
Extract _NumericLookupMixin with shared get_filter() and filter() methods.
IntegerLookup, BigIntegerLookup, and FloatLookup each inherit from it and
declare only their type-specific fields, eliminating triplicated logic.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Require a Circuit Termination target when a termination type has been
selected, so blank dynamic target fields surface an inline form error
instead of falling through to generic GFK validation for termination_id.
Add a model-level guard for the same invalid state before generic
GenericForeignKey validation runs.
Fixes#22163
Fix miscounting of total_vlan_ids when VLANGroup vid_ranges use
non-canonical bounds (e.g. '[]'). Normalize ranges to '[)' on save and
add migration to recompute existing totals. Prevent division-by-zero in
utilization queries for legacy rows with miscounted totals.
Fixes#22228
Remove `@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])` decorators
across test suites, replacing them with explicit `add_permissions()`
calls for required view permissions. Improves test clarity and ensures
permission checks are properly validated.
Fixes#22091