Skip to main content

NetBox Scope Switcher

Pick your scope once — tenant, region, site, tag, whatever you configure — and every list in NetBox narrows to it, with the filters cascading on each other.

netbox-scope-switcher adds one compact, configurable selector to the top navigation bar. Choose values across any number of scope dimensions (grouped however you like) and, as you move between sections (Devices, Prefixes, VLANs, Sites, …), each list view is automatically scoped to your selection.

It generalizes netbox-tenant-switcher: tenant is just the default dimension.

Screenshots

Grouped scope panel with a tenant selected; the Site list has cascaded to that tenant

Grouped dimensions: Tenant / Location / Tag Labels follow the NetBox UI language

Features

  • Configurable, grouped dimensions. Scope by tenant, tenant group, region, site group, site, location, tag, or any filter you declare in PLUGINS_CONFIG — arranged under your own group headings. No code changes.
  • Cascading dependent filters. Selecting values in one dimension narrows the option lists of the others, in both directions: pick a Tenant Group and only its tenants remain; pick a Tenant and Regions/Sites/Racks shrink to where that tenant is present. Powered by NetBox's own filtersets (so tree descendants and every relationship are honoured), with no hard-coded model knowledge.
  • Token-style control. One dropdown with a section per dimension: selected values shown as removable chips, a + add picker with instant search, an Any placeholder, a None option (for objects with no value), per-dimension and global clear. Chips stay name-sorted. No external JS dependencies.
  • Localized. Dimension labels come straight from each model's NetBox verbose_name, and the service words are translated via NetBox's catalog, so the panel follows the active UI language automatically.
  • Resizable & viewport-bounded panel. Drag the corner grip to resize (the size is remembered for the session); the panel never grows past the screen and scrolls internally.
  • Honest URLs. By default the plugin issues a single redirect that adds the filter params to the address bar, so links are shareable, NetBox's own filter panel shows them, and Clear filters behaves predictably. A silent mode is available.
  • Per-scope applicability. Each dimension is applied only on list views whose filterset actually supports it — a prefixes list may scope by tenant and tag but not region — computed by introspection, not hard-coding. The control dims when nothing applies to the current page.
  • Combining semantics: several values within a dimension are OR-combined; different dimensions are AND-combined; None maps to ?param=null.
  • Permission-aware. Only values the user may view are listed and selectable, and scoping only ever narrows results — NetBox object permissions still apply on top.
  • No models, no migrations. Selection lives in the session.

Compatibility

Plugin version NetBox version Python
1.0.x 4.6 3.10 – 3.12

Developed and verified against NetBox 4.6, using only stable plugin APIs (PluginTemplateExtension.navbar() / head(), plugin middleware). The CI matrix (.github/workflows/ci.yml) additionally exercises 4.4 and 4.5.

Installation

source /opt/netbox/venv/bin/activate
pip install netbox-scope-switcher

Enable it in configuration.py:

PLUGINS = ["netbox_scope_switcher"]

Restart NetBox (sudo systemctl restart netbox netbox-rq). No migrations needed.

Docker (netbox-docker)

See deploy/ for a ready-to-use Dockerfile-Plugins, docker-compose.override.yml, and plugins.py.

Configuration

Out of the box the plugin scopes by tenant only (matching netbox-tenant-switcher). To configure dimensions and grouping, set PLUGINS_CONFIG:

PLUGINS_CONFIG = {
    "netbox_scope_switcher": {
        "mode": "redirect",  # or "silent"
        "scopes": [
            {"param": "tenant_group_id", "model": "tenancy.TenantGroup", "group": "Tenant"},
            {"param": "tenant_id",       "model": "tenancy.Tenant",      "group": "Tenant"},
            {"param": "region_id",       "model": "dcim.Region",         "group": "Location"},
            {"param": "site_group_id",   "model": "dcim.SiteGroup",      "group": "Location"},
            {"param": "site_id",         "model": "dcim.Site",           "group": "Location"},
            {"param": "location_id",     "model": "dcim.Location",       "group": "Location"},
            {"param": "tag",             "model": "extras.Tag",          "group": "Tag",
             "value_field": "slug"},
        ],
    }
}

PLUGINS_CONFIG keys

Key Type Default Description
scopes list tenant only Ordered list of scope dimensions (below).
mode string redirect redirect (add params to the URL via a 302) or silent (rewrite the request in place).

Each entry in scopes:

Field Required Default Description
param yes GET parameter of the filter to apply (e.g. tenant_id, tag).
model yes app_label.ModelName the dropdown values come from.
group no Group heading to list this dimension under (translated via NetBox).
label no model verbose name Section heading. Omit it to follow the active UI language.
value_field no pk Value to put in the param: pk or slug (tags filter by slug).

The configuration is validated at startup: an unknown model or field raises a clear ImproperlyConfigured error on load, rather than a 500 at runtime.

How it works

  • Navbar widget (template_content.py) — a PluginTemplateExtension renders the control + a section per dimension via navbar(); CSS/JS are injected once via head(). Options are fetched from the values endpoint on open (so they can cascade); only the static None option is server-rendered.
  • Set endpoint (views.py) — GET /plugins/scope-switcher/set/ stores the chosen values per dimension in the session and redirects back. next is validated against the current host (no open redirects); every value is checked against the user's view permission.
  • Values endpoint (views.py) — GET /plugins/scope-switcher/values/<param>/?q=…&<other>=… returns a permission-scoped, cascaded, searchable JSON option list.
  • Cascade (cascade.py) — narrows a dimension's options to those consistent with the current selection in the others. A forward pass filters a model by every other scope its own filterset supports (Site by Region, Rack by Location, …); a reverse pass handles the "upward" direction by pivoting through a bridge model that has a FK to the target and whose filterset does support the source (Site bridges Region↔Tenant, Tenant bridges Tenant Group↔Tenant, …).
  • Applicability (applicability.py) — introspects the current list view's filterset (get_filters() / base_filters) to decide which configured params it supports; used to dim the control and to choose what to apply.
  • Middleware (middleware.py) — for ObjectListView pages, appends one ?param=<value> per selected value for each supported, not-already-present dimension. redirect mode issues a single 302; silent mode rewrites request.GET. API, GraphQL, and HTMX requests are skipped; existing query params (pagination, sort, per_page) are preserved.

Differences from netbox-tenant-switcher

netbox-tenant-switcher netbox-scope-switcher
Dimensions tenant only (hard-coded) any, configurable and grouped
Cascade filters narrow each other, both directions
Control one tenant field one control, a section + chips per dimension
Localization labels/service words follow the UI language
URL handling redirect redirect (default) or silent
Session state list of tenant ids {param: [values]} dict

Migrating

  1. pip uninstall netbox-tenant-switcher and remove it from PLUGINS.
  2. pip install netbox-scope-switcher, add "netbox_scope_switcher" to PLUGINS.
  3. Do nothing else for identical behaviour — the default config is the tenant scope. Add more dimensions to PLUGINS_CONFIG when you want them.

Sessions do not carry over (different key/shape); users simply re-pick their scope once.

Testing

Tests live in netbox_scope_switcher/tests/ and run inside a NetBox checkout:

python netbox/netbox/manage.py test netbox_scope_switcher -v 2

See .github/workflows/ci.yml for the full CI setup.

License

Apache-2.0.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

netbox_scope_switcher-1.0.1.tar.gz (34.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

netbox_scope_switcher-1.0.1-py3-none-any.whl (36.0 kB view details)

Uploaded Python 3

File details

Details for the file netbox_scope_switcher-1.0.1.tar.gz.

File metadata

  • Download URL: netbox_scope_switcher-1.0.1.tar.gz
  • Upload date:
  • Size: 34.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for netbox_scope_switcher-1.0.1.tar.gz
Algorithm Hash digest
SHA256 774d6c87c7e0c396f77a8f99109f67f29312b61c2b96d425f71f2c1f4c708631
MD5 6ac6ef209aea88cde0c280e12e511f02
BLAKE2b-256 0d1854dc07e51737b55dd698339bdb1d8855df076d48fc25c1fdbe4bd4d63596

See more details on using hashes here.

File details

Details for the file netbox_scope_switcher-1.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for netbox_scope_switcher-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 27297283d99f589bfe0e5dcd3c722ff5f311e54eab7b002e1a9413827b3f58dd
MD5 98178b518069e0ca108f93bf2c4bf392
BLAKE2b-256 906d9e39daa0ca2d04ea3ba287ba2295123215056fadb63b3623e3f6fd237595

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 files

1.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page