* Fixes#20327: Device queries are now faster when including ConfidContexts
Move .distinct() from main queryset to tag subquery to eliminate
performance bottleneck when querying devices with config contexts.
The .distinct() call on the main device queryset was causing PostgreSQL
to sort all devices before pagination, resulting in 15x slower API
responses for large installations (10k+ devices, 100+ config contexts).
Moving .distinct() to the tag subquery eliminates duplicates at their
source (GenericForeignKey tag relationships) while preserving the fix
for issues #5314 and #5387 without impacting overall query performance.
* Add performance regression test for config context annotation
The test verifies that:
- Main device queries do not use expensive DISTINCT operations
- Tag subqueries properly use DISTINCT to prevent duplicates from issue #5387
This ensures the optimization from issue #20327 (moving .distinct() from maintaining
query to tag subquery) cannot be accidentally reverted while maintaining the
correctness guarantees for issues #5314 and #5387.
* Address PR feedback, clean up new regression test
The new regression test now avoids casting the query to a string and
inspecting the string, which was brittle at best.
The new approach asserts directly against `queryset.distinct` for the
main query and then finds the subquery that we expect to have distinct
set and verifies that is in fact the case.
I also realized that the use of `connection.query_log` was problematic,
in that it didn't seem to return any queries as expected. This meant
that the test was actually not making any assertions since none of the
code inside of the for loop over `device_queries` ever ran.
* Closes#19944: Add multi-scenario CSV import testing support with cleanup
Enhanced BulkImportObjectsViewTestCase to support multiple CSV import scenarios via dictionary format,
where each scenario runs as a separate subtest with automatic cleanup. This enables testing different
import configurations (e.g., with/without optional fields) in a single test run with clear output
showing which scenario is being tested.
Introduces cleanupSubTest() context manager that uses database savepoints to automatically roll back
changes between subtests, providing test isolation similar to separate test methods. This allows
subtests to create/modify objects without affecting subsequent subtests in the same test method.
Added post_import_callback parameter to bulk import tests, allowing child classes to inject custom
assertions that run before database cleanup. This solves the inheritance problem where child classes
need to verify imported data but the parent's cleanup would roll back the data before assertions could
run.
The callback approach is cleaner than conditional cleanup parameters - it makes the execution timing
explicit and maintains test isolation while still allowing extensibility.
* Fixup ModuleTypeTestCase bulk import test to work with callback mechamisn
* Update CableTestCase to use expanded CSV scenario testing
* Remove unneeded permission cleanup
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Consolidate scenario name retrieval into method
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
Replaces inline plugin title HTML with a reusable template in
`template_code.py`. Adds a default icon for plugins without custom icons
and updates the table logic to use this template.
Removes redundant logic from the `render_title_long` method to improve
maintainability.
Changes the `order_by` field in `plugins.py` from `name` to
`title_long`.
Fixes#20264
Introduces a sync button in the DataSource table for improved user
interaction. Enables users to trigger sync actions directly from the
table, with context-sensitive availability based on permissions and
record status.
Closes#19547
This fix actually fixes this for all valid JSON values that evaluate to
`False` in Python when loaded and cast to bool:
`bool(json.loads(<val>))`.
- `{}`
- `[]`
- `0`
- `False`
This does not change the behavior of `()` or `""` which are both
explicitly cited as "empty" values on `JSONField`.
Adds the `accessor` attribute with `tables.A('is_loaded')` to the
`is_installed` column in the plugin's table. This ensures proper data
access and improves the table's functionality.
Fixes#19744