Compare commits

...

8 Commits

Author SHA1 Message Date
Jeremy Stretch
8f5f91fcfe Closes #21259: Cache ObjectType results for the duration of a request (#21287) 2026-01-26 15:07:13 -08:00
Martin Hauser
1a2175127e Fixes #21202: Avoid clearing scope on clone (#21265) 2026-01-26 16:14:36 -06:00
Martin Hauser
e859807d1d docs(guides): Update Ubuntu reference to 24.04
Update the installation and administration guides to reference
Ubuntu 24.04 instead of 22.04 where applicable, and refresh examples
to match NetBox v4.5.

This includes updates to Python version requirements, NetBox shell
commands, Redis configuration, and sample outputs to align with current
compatibility and best practices.

Fixes #21297
2026-01-26 15:43:59 -05:00
Jeremy Stretch
a8c997ff29 Closes #21260: Defer object serialization for events pipeline (#21286) 2026-01-26 14:35:00 -06:00
adionit7
4a28ab98f4 Fixes #21115: Include attribute_data in ModuleType YAML export
- Added airflow and attribute_data fields to ModuleType.to_yaml() method
- Ensures custom JSON properties from module type profiles are properly exported
- Maintains consistency with import functionality in ModuleTypeImportForm
2026-01-26 15:01:21 -05:00
Martin Hauser
3636d55017 fix(nav): Show Authentication admin menu items based on object perms (#21283)
Replace hardcoded menu entries for Users, Groups, API Tokens, and
Permissions with `get_model_item()`. This drops the `staff_only` gate
and relies on the standard model permission checks, restoring visibility
of these Admin menu items for non-superusers with the relevant object
permissions.

Fixes #21242
2026-01-26 11:34:46 -08:00
Aditya Sharma
aa69e96818 Fixes #21173: Fix plugin menu registration order timing issue (#21248)
* Fixes #21173: Fix plugin menu registration order timing issue

- Converted static MENUS list to dynamic get_menus() function
- Ensures plugin menus are built at request time after all plugins complete ready()
- Fixes issue where only first few plugin menus appeared in navigation sidebar
- Updated navigation template tag to call get_menus() dynamically

* Fix ruff linting errors

- Add missing blank line before get_menus() function definition
- Remove trailing whitespace

* Add @cache decorator to get_menus() for performance optimization

Per reviewer feedback, the menu list is now cached since it doesn't change
without a Django restart. This eliminates redundant list building on each request.

---------

Co-authored-by: adionit7 <adionit7@users.noreply.github.com>
2026-01-26 10:34:57 -08:00
github-actions
a9e50238eb Update source translation strings 2026-01-24 05:03:22 +00:00
17 changed files with 351 additions and 350 deletions

View File

@@ -3,29 +3,41 @@
NetBox includes a Python management shell within which objects can be directly queried, created, modified, and deleted. To enter the shell, run the following command:
```
./manage.py nbshell
cd /opt/netbox
source /opt/netbox/venv/bin/activate
python3 netbox/manage.py nbshell
```
This will launch a lightly customized version of [the built-in Django shell](https://docs.djangoproject.com/en/stable/ref/django-admin/#shell) with all relevant NetBox models pre-loaded. (If desired, the stock Django shell is also available by executing `./manage.py shell`.)
This will launch a lightly customized version of [the built-in Django shell](https://docs.djangoproject.com/en/stable/ref/django-admin/#shell) with all relevant NetBox models preloaded. (If desired, the stock Django shell is also available by executing `./manage.py shell`.)
```
$ ./manage.py nbshell
(venv) $ python3 netbox/manage.py nbshell
### NetBox interactive shell (localhost)
### Python 3.7.10 | Django 3.2.5 | NetBox 3.0
### lsmodels() will show available models. Use help(<model>) for more info.
### Python v3.12.3 | Django v5.2.10 | NetBox Community v4.5.1
### lsapps() & lsmodels() will show available models. Use help(<model>) for more info.
```
The function `lsmodels()` will print a list of all available NetBox models:
```
>>> lsmodels()
DCIM:
ConsolePort
ConsolePortTemplate
ConsoleServerPort
ConsoleServerPortTemplate
Device
...
DCIM:
dcim.Cable
dcim.CableTermination
dcim.ConsolePort
dcim.ConsolePortTemplate
dcim.ConsoleServerPort
dcim.ConsoleServerPortTemplate
dcim.Device
...
```
To exit the NetBox shell, type `exit()` or press `Ctrl+D`.
```
>>> exit()
(venv) $
```
!!! warning
@@ -114,7 +126,7 @@ Reverse relationships can be traversed as well. For example, the following will
>>> Device.objects.filter(interfaces__name="em0")
```
Character fields can be filtered against partial matches using the `contains` or `icontains` field lookup (the later of which is case-insensitive).
Character fields can be filtered against partial matches using the `contains` or `icontains` field lookup (the latter of which is case-insensitive).
```
>>> Device.objects.filter(name__icontains="testdevice")

View File

@@ -51,14 +51,14 @@ You can verify that authentication works by executing the `psql` command and pas
```no-highlight
$ psql --username netbox --password --host localhost netbox
Password for user netbox:
psql (12.5 (Ubuntu 12.5-0ubuntu0.20.04.1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Password:
psql (16.11 (Ubuntu 16.11-0ubuntu0.24.04.1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.
netbox=> \conninfo
You are connected to database "netbox" as user "netbox" on host "localhost" (address "127.0.0.1") at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
netbox=> \q
```

View File

@@ -36,7 +36,7 @@ sudo ln -s /opt/netbox-X.Y.Z/ /opt/netbox
```
!!! note
It is recommended to install NetBox in a directory named for its version number. For example, NetBox v3.0.0 would be installed into `/opt/netbox-3.0.0`, and a symlink from `/opt/netbox/` would point to this location. (You can verify this configuration with the command `ls -l /opt | grep netbox`.) This allows for future releases to be installed in parallel without interrupting the current installation. When changing to the new release, only the symlink needs to be updated.
It is recommended to install NetBox in a directory named for its version number. For example, NetBox v4.0.0 would be installed into `/opt/netbox-4.0.0`, and a symlink from `/opt/netbox/` would point to this location. (You can verify this configuration with the command `ls -l /opt | grep netbox`.) This allows for future releases to be installed in parallel without interrupting the current installation. When changing to the new release, only the symlink needs to be updated.
### Option B: Clone the Git Repository
@@ -63,12 +63,12 @@ This command should generate output similar to the following:
```
Cloning into '.'...
remote: Enumerating objects: 996, done.
remote: Counting objects: 100% (996/996), done.
remote: Compressing objects: 100% (935/935), done.
remote: Total 996 (delta 148), reused 386 (delta 34), pack-reused 0
Receiving objects: 100% (996/996), 4.26 MiB | 9.81 MiB/s, done.
Resolving deltas: 100% (148/148), done.
remote: Enumerating objects: 148317, done.
remote: Counting objects: 100% (183/183), done.
remote: Compressing objects: 100% (115/115), done.
remote: Total 148317 (delta 127), reused 68 (delta 68), pack-reused 148134 (from 3)
Receiving objects: 100% (148317/148317), 165.12 MiB | 28.71 MiB/s, done.
Resolving deltas: 100% (116428/116428), done.
```
Finally, check out the tag for the desired release. You can find these on our [releases page](https://github.com/netbox-community/netbox/releases). Replace `vX.Y.Z` with your selected release tag below.
@@ -102,7 +102,8 @@ sudo cp configuration_example.py configuration.py
Open `configuration.py` with your preferred editor to begin configuring NetBox. NetBox offers [many configuration parameters](../configuration/index.md), but only the following four are required for new installations:
* `ALLOWED_HOSTS`
* `DATABASES` (or `DATABASE`)
* `API_TOKEN_PEPPERS`
* `DATABASES`
* `REDIS`
* `SECRET_KEY`
@@ -158,7 +159,7 @@ DATABASES = {
### REDIS
Redis is a in-memory key-value store used by NetBox for caching and background task queuing. Redis typically requires minimal configuration; the values below should suffice for most installations. See the [configuration documentation](../configuration/required-parameters.md#redis) for more detail on individual parameters.
Redis is an in-memory key-value store used by NetBox for caching and background task queuing. Redis typically requires minimal configuration; the values below should suffice for most installations. See the [configuration documentation](../configuration/required-parameters.md#redis) for more detail on individual parameters.
Note that NetBox requires the specification of two separate Redis databases: `tasks` and `caching`. These may both be provided by the same Redis service, however each should have a unique numeric database ID.
@@ -252,7 +253,7 @@ Once NetBox has been configured, we're ready to proceed with the actual installa
sudo /opt/netbox/upgrade.sh
```
Note that **Python 3.12 or later is required** for NetBox v4.5 and later releases. If the default Python installation on your server is set to a lesser version, pass the path to the supported installation as an environment variable named `PYTHON`. (Note that the environment variable must be passed _after_ the `sudo` command.)
Note that **Python 3.12 or later is required** for NetBox v4.5 and later releases. If the default Python installation on your server is set to a lesser version, pass the path to the supported installation as an environment variable named `PYTHON`. (Note that the environment variable must be passed _after_ the `sudo` command.)
```no-highlight
sudo PYTHON=/usr/bin/python3.12 /opt/netbox/upgrade.sh
@@ -295,13 +296,12 @@ python3 manage.py runserver 0.0.0.0:8000 --insecure
If successful, you should see output similar to the following:
```no-highlight
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
August 30, 2021 - 18:02:23
Django version 3.2.6, using settings 'netbox.settings'
Starting development server at http://127.0.0.1:8000/
January 26, 2026 - 17:00:00
Django version 5.2.10, using settings 'netbox.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
```

View File

@@ -43,16 +43,22 @@ You should see output similar to the following:
```no-highlight
● netbox.service - NetBox WSGI Service
Loaded: loaded (/etc/systemd/system/netbox.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2021-08-30 04:02:36 UTC; 14h ago
Loaded: loaded (/etc/systemd/system/netbox.service; enabled; preset: enabled)
Active: active (running) since Mon 2026-01-26 11:00:00 CST; 7s ago
Docs: https://docs.netbox.dev/
Main PID: 1140492 (gunicorn)
Tasks: 19 (limit: 4683)
Memory: 666.2M
Main PID: 7283 (gunicorn)
Tasks: 6 (limit: 4545)
Memory: 556.1M (peak: 556.3M)
CPU: 3.387s
CGroup: /system.slice/netbox.service
├─1140492 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /va>
├─1140513 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /va>
├─1140514 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /va>
├─7283 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox>
├─7285 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox>
├─7286 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox>
├─7287 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox>
├─7288 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox>
└─7289 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox>
Jan 26 11:00:00 netbox systemd[1]: Started netbox.service - NetBox WSGI Service.
...
```

View File

@@ -3,7 +3,7 @@
This documentation provides example configurations for both [nginx](https://www.nginx.com/resources/wiki/) and [Apache](https://httpd.apache.org/docs/current/), though any HTTP server which supports WSGI should be compatible.
!!! info
For the sake of brevity, only Ubuntu 20.04 instructions are provided here. These tasks are not unique to NetBox and should carry over to other distributions with minimal changes. Please consult your distribution's documentation for assistance if needed.
For the sake of brevity, only Ubuntu 24.04 instructions are provided here. These tasks are not unique to NetBox and should carry over to other distributions with minimal changes. Please consult your distribution's documentation for assistance if needed.
## Obtain an SSL Certificate

View File

@@ -12,12 +12,12 @@
</div>
The installation instructions provided here have been tested to work on Ubuntu 22.04. The particular commands needed to install dependencies on other distributions may vary significantly. Unfortunately, this is outside the control of the NetBox maintainers. Please consult your distribution's documentation for assistance with any errors.
The installation instructions provided here have been tested to work on Ubuntu 24.04. The particular commands needed to install dependencies on other distributions may vary significantly. Unfortunately, this is outside the control of the NetBox maintainers. Please consult your distribution's documentation for assistance with any errors.
The following sections detail how to set up a new instance of NetBox:
1. [PostgreSQL database](1-postgresql.md)
1. [Redis](2-redis.md)
2. [Redis](2-redis.md)
3. [NetBox components](3-netbox.md)
4. [Gunicorn](4a-gunicorn.md) or [uWSGI](4b-uwsgi.md)
5. [HTTP server](5-http-server.md)

View File

@@ -65,7 +65,7 @@ Download and extract the latest version:
```no-highlight
# Set $NEWVER to the NetBox version being installed
NEWVER=3.5.0
NEWVER=4.5.0
wget https://github.com/netbox-community/netbox/archive/v$NEWVER.tar.gz
sudo tar -xzf v$NEWVER.tar.gz -C /opt
sudo ln -sfn /opt/netbox-$NEWVER/ /opt/netbox
@@ -75,7 +75,7 @@ Copy `local_requirements.txt`, `configuration.py`, and `ldap_config.py` (if pres
```no-highlight
# Set $OLDVER to the NetBox version currently installed
OLDVER=3.4.9
OLDVER=4.4.10
sudo cp /opt/netbox-$OLDVER/local_requirements.txt /opt/netbox/
sudo cp /opt/netbox-$OLDVER/netbox/netbox/configuration.py /opt/netbox/netbox/netbox/
sudo cp /opt/netbox-$OLDVER/netbox/netbox/ldap_config.py /opt/netbox/netbox/netbox/
@@ -116,7 +116,7 @@ Check out the desired release by specifying its tag. For example:
```
cd /opt/netbox && \
sudo git fetch --tags && \
sudo git checkout v4.2.7
sudo git checkout v4.5.0
```
## 4. Run the Upgrade Script
@@ -128,7 +128,7 @@ sudo ./upgrade.sh
```
!!! warning
If the default version of Python is not at least 3.10, you'll need to pass the path to a supported Python version as an environment variable when calling the upgrade script. For example:
If the default version of Python is not **at least 3.12**, you'll need to pass the path to a supported Python version as an environment variable when calling the upgrade script. For example:
```no-highlight
sudo PYTHON=/usr/bin/python3.12 ./upgrade.sh

View File

@@ -9,6 +9,7 @@ from django.db import connection, models
from django.db.models import Q
from django.utils.translation import gettext as _
from netbox.context import query_cache
from netbox.plugins import PluginConfig
from netbox.registry import registry
from utilities.string import title
@@ -70,6 +71,12 @@ class ObjectTypeManager(models.Manager):
"""
from netbox.models.features import get_model_features, model_is_public
# Check the request cache before hitting the database
cache = query_cache.get()
if cache is not None:
if ot := cache['object_types'].get((model._meta.model, for_concrete_model)):
return ot
# TODO: Remove this in NetBox v5.0
# If the ObjectType table has not yet been provisioned (e.g. because we're in a pre-v4.4 migration),
# fall back to ContentType.
@@ -96,6 +103,10 @@ class ObjectTypeManager(models.Manager):
features=get_model_features(model),
)[0]
# Populate the request cache to avoid redundant lookups
if cache is not None:
cache['object_types'][(model._meta.model, for_concrete_model)] = ot
return ot
def get_for_models(self, *models, for_concrete_models=True):

View File

@@ -75,7 +75,7 @@ class ScopedForm(forms.Form):
except ObjectDoesNotExist:
pass
if self.instance and scope_type_id != self.instance.scope_type_id:
if self.instance and self.instance.pk and scope_type_id != self.instance.scope_type_id:
self.initial['scope'] = None
else:

View File

@@ -155,6 +155,8 @@ class ModuleType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
'description': self.description,
'weight': float(self.weight) if self.weight is not None else None,
'weight_unit': self.weight_unit,
'airflow': self.airflow,
'attribute_data': self.attribute_data,
'comments': self.comments,
}

View File

@@ -1,5 +1,5 @@
import logging
from collections import defaultdict
from collections import UserDict, defaultdict
from django.conf import settings
from django.utils import timezone
@@ -12,7 +12,6 @@ from core.models import ObjectType
from netbox.config import get_config
from netbox.constants import RQ_QUEUE_DEFAULT
from netbox.models.features import has_feature
from users.models import User
from utilities.api import get_serializer_for_model
from utilities.request import copy_safe_request
from utilities.rqworker import get_rq_retry
@@ -23,6 +22,21 @@ from .models import EventRule
logger = logging.getLogger('netbox.events_processor')
class EventContext(UserDict):
"""
A custom dictionary that automatically serializes its associated object on demand.
"""
# We're emulating a dictionary here (rather than using a custom class) because prior to NetBox v4.5.2, events were
# queued as dictionaries for processing by handles in EVENTS_PIPELINE. We need to avoid introducing any breaking
# changes until a suitable minor release.
def __getitem__(self, item):
if item == 'data' and 'data' not in self:
data = serialize_for_event(self['object'])
self.__setitem__('data', data)
return super().__getitem__(item)
def serialize_for_event(instance):
"""
Return a serialized representation of the given instance suitable for use in a queued event.
@@ -66,37 +80,42 @@ def enqueue_event(queue, instance, request, event_type):
assert instance.pk is not None
key = f'{app_label}.{model_name}:{instance.pk}'
if key in queue:
queue[key]['data'] = serialize_for_event(instance)
queue[key]['snapshots']['postchange'] = get_snapshots(instance, event_type)['postchange']
# If the object is being deleted, update any prior "update" event to "delete"
if event_type == OBJECT_DELETED:
queue[key]['event_type'] = event_type
else:
queue[key] = {
'object_type': ObjectType.objects.get_for_model(instance),
'object_id': instance.pk,
'event_type': event_type,
'data': serialize_for_event(instance),
'snapshots': get_snapshots(instance, event_type),
'request': request,
queue[key] = EventContext(
object_type=ObjectType.objects.get_for_model(instance),
object_id=instance.pk,
object=instance,
event_type=event_type,
snapshots=get_snapshots(instance, event_type),
request=request,
user=request.user,
# Legacy request attributes for backward compatibility
'username': request.user.username,
'request_id': request.id,
}
username=request.user.username,
request_id=request.id,
)
# Force serialization of objects prior to them actually being deleted
if event_type == OBJECT_DELETED:
queue[key]['data'] = serialize_for_event(instance)
def process_event_rules(event_rules, object_type, event_type, data, username=None, snapshots=None, request=None):
user = None # To be resolved from the username if needed
def process_event_rules(event_rules, object_type, event):
"""
Process a list of EventRules against an event.
"""
for event_rule in event_rules:
# Evaluate event rule conditions (if any)
if not event_rule.eval_conditions(data):
if not event_rule.eval_conditions(event['data']):
continue
# Compile event data
event_data = event_rule.action_data or {}
event_data.update(data)
event_data.update(event['data'])
# Webhooks
if event_rule.action_type == EventRuleActionChoices.WEBHOOK:
@@ -109,50 +128,41 @@ def process_event_rules(event_rules, object_type, event_type, data, username=Non
params = {
"event_rule": event_rule,
"object_type": object_type,
"event_type": event_type,
"event_type": event['event_type'],
"data": event_data,
"snapshots": snapshots,
"snapshots": event.get('snapshots'),
"timestamp": timezone.now().isoformat(),
"username": username,
"username": event['username'],
"retry": get_rq_retry()
}
if snapshots:
params["snapshots"] = snapshots
if request:
if 'request' in event:
# Exclude FILES - webhooks don't need uploaded files,
# which can cause pickle errors with Pillow.
params["request"] = copy_safe_request(request, include_files=False)
params['request'] = copy_safe_request(event['request'], include_files=False)
# Enqueue the task
rq_queue.enqueue(
"extras.webhooks.send_webhook",
**params
)
rq_queue.enqueue('extras.webhooks.send_webhook', **params)
# Scripts
elif event_rule.action_type == EventRuleActionChoices.SCRIPT:
# Resolve the script from action parameters
script = event_rule.action_object.python_class()
# Retrieve the User if not already resolved
if user is None:
user = User.objects.get(username=username)
# Enqueue a Job to record the script's execution
from extras.jobs import ScriptJob
params = {
"instance": event_rule.action_object,
"name": script.name,
"user": user,
"user": event['user'],
"data": event_data
}
if snapshots:
params["snapshots"] = snapshots
if request:
params["request"] = copy_safe_request(request)
ScriptJob.enqueue(
**params
)
if 'snapshots' in event:
params['snapshots'] = event['snapshots']
if 'request' in event:
params['request'] = copy_safe_request(event['request'])
# Enqueue the job
ScriptJob.enqueue(**params)
# Notification groups
elif event_rule.action_type == EventRuleActionChoices.NOTIFICATION:
@@ -161,7 +171,7 @@ def process_event_rules(event_rules, object_type, event_type, data, username=Non
object_type=object_type,
object_id=event_data['id'],
object_repr=event_data.get('display'),
event_type=event_type
event_type=event['event_type']
)
else:
@@ -173,6 +183,8 @@ def process_event_rules(event_rules, object_type, event_type, data, username=Non
def process_event_queue(events):
"""
Flush a list of object representation to RQ for EventRule processing.
This is the default processor listed in EVENTS_PIPELINE.
"""
events_cache = defaultdict(dict)
@@ -192,11 +204,7 @@ def process_event_queue(events):
process_event_rules(
event_rules=event_rules,
object_type=object_type,
event_type=event['event_type'],
data=event['data'],
username=event['username'],
snapshots=event['snapshots'],
request=event['request'],
event=event,
)

View File

@@ -4,7 +4,7 @@ from django.dispatch import receiver
from core.events import *
from core.signals import job_end, job_start
from extras.events import process_event_rules
from extras.events import EventContext, process_event_rules
from extras.models import EventRule, Notification, Subscription
from netbox.config import get_config
from netbox.models.features import has_feature
@@ -102,14 +102,12 @@ def process_job_start_event_rules(sender, **kwargs):
enabled=True,
object_types=sender.object_type
)
username = sender.user.username if sender.user else None
process_event_rules(
event_rules=event_rules,
object_type=sender.object_type,
event = EventContext(
event_type=JOB_STARTED,
data=sender.data,
username=username
user=sender.user,
)
process_event_rules(event_rules, sender.object_type, event)
@receiver(job_end)
@@ -122,14 +120,12 @@ def process_job_end_event_rules(sender, **kwargs):
enabled=True,
object_types=sender.object_type
)
username = sender.user.username if sender.user else None
process_event_rules(
event_rules=event_rules,
object_type=sender.object_type,
event = EventContext(
event_type=JOB_COMPLETED,
data=sender.data,
username=username
user=sender.user,
)
process_event_rules(event_rules, sender.object_type, event)
#

View File

@@ -3,8 +3,10 @@ from contextvars import ContextVar
__all__ = (
'current_request',
'events_queue',
'query_cache',
)
current_request = ContextVar('current_request', default=None)
events_queue = ContextVar('events_queue', default=dict())
query_cache = ContextVar('query_cache', default=None)

View File

@@ -1,6 +1,7 @@
from collections import defaultdict
from contextlib import contextmanager
from netbox.context import current_request, events_queue
from netbox.context import current_request, events_queue, query_cache
from netbox.utils import register_request_processor
from extras.events import flush_events
@@ -16,6 +17,7 @@ def event_tracking(request):
"""
current_request.set(request)
events_queue.set({})
query_cache.set(defaultdict(dict))
yield
@@ -26,3 +28,4 @@ def event_tracking(request):
# Clear context vars
current_request.set(None)
events_queue.set({})
query_cache.set(None)

View File

@@ -1,3 +1,5 @@
from functools import cache
from django.utils.translation import gettext_lazy as _
from netbox.registry import registry
@@ -409,60 +411,10 @@ ADMIN_MENU = Menu(
MenuGroup(
label=_('Authentication'),
items=(
MenuItem(
link='users:user_list',
link_text=_('Users'),
staff_only=True,
permissions=['users.view_user'],
buttons=(
MenuItemButton(
link='users:user_add',
title='Add',
icon_class='mdi mdi-plus-thick',
permissions=['users.add_user']
),
MenuItemButton(
link='users:user_bulk_import',
title='Import',
icon_class='mdi mdi-upload',
permissions=['users.add_user']
)
)
),
MenuItem(
link='users:group_list',
link_text=_('Groups'),
staff_only=True,
permissions=['users.view_group'],
buttons=(
MenuItemButton(
link='users:group_add',
title='Add',
icon_class='mdi mdi-plus-thick',
permissions=['users.add_group']
),
MenuItemButton(
link='users:group_bulk_import',
title='Import',
icon_class='mdi mdi-upload',
permissions=['users.add_group']
)
)
),
MenuItem(
link='users:token_list',
link_text=_('API Tokens'),
staff_only=True,
permissions=['users.view_token'],
buttons=get_model_buttons('users', 'token')
),
MenuItem(
link='users:objectpermission_list',
link_text=_('Permissions'),
staff_only=True,
permissions=['users.view_objectpermission'],
buttons=get_model_buttons('users', 'objectpermission', actions=['add'])
),
get_model_item('users', 'user', _('Users')),
get_model_item('users', 'group', _('Groups')),
get_model_item('users', 'token', _('API Tokens')),
get_model_item('users', 'objectpermission', _('Permissions'), actions=['add']),
),
),
MenuGroup(
@@ -501,40 +453,49 @@ ADMIN_MENU = Menu(
),
)
MENUS = [
ORGANIZATION_MENU,
RACKS_MENU,
DEVICES_MENU,
CONNECTIONS_MENU,
WIRELESS_MENU,
IPAM_MENU,
VPN_MENU,
VIRTUALIZATION_MENU,
CIRCUITS_MENU,
POWER_MENU,
PROVISIONING_MENU,
CUSTOMIZATION_MENU,
OPERATIONS_MENU,
]
# Add top-level plugin menus
for menu in registry['plugins']['menus']:
MENUS.append(menu)
# Add the default "plugins" menu
if registry['plugins']['menu_items']:
# Build the default plugins menu
groups = [
MenuGroup(label=label, items=items)
for label, items in registry['plugins']['menu_items'].items()
@cache
def get_menus():
"""
Dynamically build and return the list of navigation menus.
This ensures plugin menus registered during app initialization are included.
The result is cached since menus don't change without a Django restart.
"""
menus = [
ORGANIZATION_MENU,
RACKS_MENU,
DEVICES_MENU,
CONNECTIONS_MENU,
WIRELESS_MENU,
IPAM_MENU,
VPN_MENU,
VIRTUALIZATION_MENU,
CIRCUITS_MENU,
POWER_MENU,
PROVISIONING_MENU,
CUSTOMIZATION_MENU,
OPERATIONS_MENU,
]
plugins_menu = Menu(
label=_("Plugins"),
icon_class="mdi mdi-puzzle",
groups=groups
)
MENUS.append(plugins_menu)
# Add the admin menu last
MENUS.append(ADMIN_MENU)
# Add top-level plugin menus
for menu in registry['plugins']['menus']:
menus.append(menu)
# Add the default "plugins" menu
if registry['plugins']['menu_items']:
# Build the default plugins menu
groups = [
MenuGroup(label=label, items=items)
for label, items in registry['plugins']['menu_items'].items()
]
plugins_menu = Menu(
label=_("Plugins"),
icon_class="mdi mdi-puzzle",
groups=groups
)
menus.append(plugins_menu)
# Add the admin menu last
menus.append(ADMIN_MENU)
return menus

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-01-22 05:07+0000\n"
"POT-Creation-Date: 2026-01-24 05:03+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -181,9 +181,9 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:1154 netbox/dcim/forms/filtersets.py:1249
#: netbox/dcim/forms/filtersets.py:1287 netbox/dcim/forms/filtersets.py:1992
#: netbox/dcim/forms/filtersets.py:2016 netbox/dcim/forms/filtersets.py:2040
#: netbox/dcim/forms/model_forms.py:143 netbox/dcim/forms/model_forms.py:171
#: netbox/dcim/forms/model_forms.py:242 netbox/dcim/forms/model_forms.py:558
#: netbox/dcim/forms/model_forms.py:819 netbox/dcim/forms/object_create.py:292
#: netbox/dcim/forms/model_forms.py:145 netbox/dcim/forms/model_forms.py:173
#: netbox/dcim/forms/model_forms.py:244 netbox/dcim/forms/model_forms.py:560
#: netbox/dcim/forms/model_forms.py:829 netbox/dcim/forms/object_create.py:292
#: netbox/dcim/tables/devices.py:155 netbox/dcim/tables/power.py:25
#: netbox/dcim/tables/power.py:89 netbox/dcim/tables/racks.py:110
#: netbox/dcim/tables/racks.py:193 netbox/dcim/tables/sites.py:101
@@ -406,7 +406,7 @@ msgstr ""
#: netbox/circuits/forms/bulk_edit.py:42 netbox/circuits/forms/filtersets.py:64
#: netbox/circuits/forms/model_forms.py:43
#: netbox/circuits/tables/providers.py:32 netbox/dcim/forms/bulk_edit.py:131
#: netbox/dcim/forms/filtersets.py:224 netbox/dcim/forms/model_forms.py:130
#: netbox/dcim/forms/filtersets.py:224 netbox/dcim/forms/model_forms.py:132
#: netbox/dcim/tables/sites.py:73 netbox/ipam/models/asns.py:155
#: netbox/ipam/tables/asn.py:37 netbox/ipam/views.py:269
#: netbox/netbox/navigation/menu.py:179 netbox/netbox/navigation/menu.py:182
@@ -511,7 +511,7 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:1577 netbox/dcim/forms/filtersets.py:1682
#: netbox/dcim/forms/filtersets.py:1730 netbox/dcim/forms/filtersets.py:1749
#: netbox/dcim/forms/filtersets.py:1772 netbox/dcim/forms/filtersets.py:1791
#: netbox/dcim/forms/model_forms.py:800 netbox/dcim/forms/model_forms.py:806
#: netbox/dcim/forms/model_forms.py:810 netbox/dcim/forms/model_forms.py:816
#: netbox/dcim/forms/object_import.py:85 netbox/dcim/forms/object_import.py:114
#: netbox/dcim/forms/object_import.py:127 netbox/dcim/tables/devices.py:180
#: netbox/dcim/tables/devices.py:862 netbox/dcim/tables/power.py:73
@@ -804,9 +804,9 @@ msgstr ""
#: netbox/circuits/forms/model_forms.py:137
#: netbox/circuits/forms/model_forms.py:233
#: netbox/circuits/forms/model_forms.py:335
#: netbox/dcim/forms/model_forms.py:145 netbox/dcim/forms/model_forms.py:186
#: netbox/dcim/forms/model_forms.py:273 netbox/dcim/forms/model_forms.py:330
#: netbox/dcim/forms/model_forms.py:863 netbox/dcim/forms/model_forms.py:1877
#: netbox/dcim/forms/model_forms.py:147 netbox/dcim/forms/model_forms.py:188
#: netbox/dcim/forms/model_forms.py:275 netbox/dcim/forms/model_forms.py:332
#: netbox/dcim/forms/model_forms.py:873 netbox/dcim/forms/model_forms.py:1887
#: netbox/ipam/forms/bulk_edit.py:380 netbox/ipam/forms/model_forms.py:67
#: netbox/ipam/forms/model_forms.py:84 netbox/ipam/forms/model_forms.py:115
#: netbox/ipam/forms/model_forms.py:136 netbox/ipam/forms/model_forms.py:160
@@ -982,7 +982,7 @@ msgstr ""
#: netbox/circuits/forms/bulk_edit.py:255
#: netbox/circuits/forms/bulk_import.py:188
#: netbox/circuits/forms/filtersets.py:305
#: netbox/circuits/tables/circuits.py:202 netbox/dcim/forms/model_forms.py:646
#: netbox/circuits/tables/circuits.py:202 netbox/dcim/forms/model_forms.py:656
#: netbox/templates/circuits/circuitgroupassignment.html:34
#: netbox/templates/dcim/panels/virtual_chassis_members.html:11
#: netbox/templates/dcim/virtualchassis.html:58
@@ -1012,8 +1012,8 @@ msgstr ""
#: netbox/dcim/forms/bulk_import.py:262 netbox/dcim/forms/bulk_import.py:1193
#: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:865
#: netbox/dcim/forms/filtersets.py:1872 netbox/dcim/forms/filtersets.py:1912
#: netbox/dcim/forms/model_forms.py:255 netbox/dcim/forms/model_forms.py:1214
#: netbox/dcim/forms/model_forms.py:1697 netbox/dcim/forms/object_import.py:182
#: netbox/dcim/forms/model_forms.py:257 netbox/dcim/forms/model_forms.py:1224
#: netbox/dcim/forms/model_forms.py:1707 netbox/dcim/forms/object_import.py:182
#: netbox/dcim/tables/devices.py:171 netbox/dcim/tables/devices.py:857
#: netbox/dcim/tables/devices.py:983 netbox/dcim/tables/devicetypes.py:317
#: netbox/dcim/tables/racks.py:117 netbox/extras/filtersets.py:708
@@ -1132,9 +1132,9 @@ msgstr ""
#: netbox/circuits/forms/bulk_import.py:258
#: netbox/circuits/forms/model_forms.py:358
#: netbox/circuits/tables/virtual_circuits.py:108
#: netbox/dcim/forms/bulk_import.py:1324 netbox/dcim/forms/model_forms.py:1288
#: netbox/dcim/forms/model_forms.py:1557 netbox/dcim/forms/model_forms.py:1738
#: netbox/dcim/forms/model_forms.py:1773 netbox/dcim/forms/model_forms.py:1898
#: netbox/dcim/forms/bulk_import.py:1324 netbox/dcim/forms/model_forms.py:1298
#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/model_forms.py:1748
#: netbox/dcim/forms/model_forms.py:1783 netbox/dcim/forms/model_forms.py:1908
#: netbox/dcim/tables/connections.py:65 netbox/dcim/tables/devices.py:1150
#: netbox/ipam/forms/bulk_import.py:319 netbox/ipam/forms/model_forms.py:280
#: netbox/ipam/forms/model_forms.py:289 netbox/ipam/tables/fhrp.py:61
@@ -1181,8 +1181,8 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:1554 netbox/dcim/forms/filtersets.py:1721
#: netbox/dcim/forms/filtersets.py:1764 netbox/dcim/forms/filtersets.py:1806
#: netbox/dcim/forms/filtersets.py:1837 netbox/dcim/forms/filtersets.py:1863
#: netbox/dcim/forms/model_forms.py:185 netbox/dcim/forms/model_forms.py:247
#: netbox/dcim/forms/model_forms.py:563 netbox/dcim/forms/model_forms.py:824
#: netbox/dcim/forms/model_forms.py:187 netbox/dcim/forms/model_forms.py:249
#: netbox/dcim/forms/model_forms.py:565 netbox/dcim/forms/model_forms.py:834
#: netbox/dcim/tables/devices.py:159 netbox/dcim/tables/power.py:29
#: netbox/dcim/tables/racks.py:106 netbox/dcim/tables/racks.py:198
#: netbox/extras/filtersets.py:692 netbox/extras/forms/filtersets.py:429
@@ -1234,7 +1234,7 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:1146 netbox/dcim/forms/filtersets.py:1235
#: netbox/dcim/forms/filtersets.py:1274 netbox/dcim/forms/filtersets.py:1984
#: netbox/dcim/forms/filtersets.py:2008 netbox/dcim/forms/filtersets.py:2032
#: netbox/dcim/forms/model_forms.py:117 netbox/dcim/forms/object_create.py:276
#: netbox/dcim/forms/model_forms.py:119 netbox/dcim/forms/object_create.py:276
#: netbox/dcim/tables/devices.py:145 netbox/dcim/tables/sites.py:64
#: netbox/extras/filtersets.py:659 netbox/ipam/forms/bulk_edit.py:401
#: netbox/ipam/forms/filtersets.py:233 netbox/ipam/forms/filtersets.py:454
@@ -1292,7 +1292,7 @@ msgstr ""
#: netbox/circuits/forms/filtersets.py:302
#: netbox/circuits/forms/model_forms.py:245
#: netbox/circuits/tables/circuits.py:186 netbox/dcim/forms/bulk_edit.py:115
#: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/model_forms.py:123
#: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/model_forms.py:125
#: netbox/dcim/tables/sites.py:68 netbox/extras/forms/filtersets.py:633
#: netbox/ipam/filtersets.py:998 netbox/ipam/forms/bulk_edit.py:420
#: netbox/ipam/forms/bulk_import.py:492 netbox/ipam/forms/model_forms.py:558
@@ -1851,9 +1851,9 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:1840 netbox/dcim/forms/filtersets.py:1851
#: netbox/dcim/forms/filtersets.py:1866 netbox/dcim/forms/filtersets.py:1907
#: netbox/dcim/forms/filtersets.py:2000 netbox/dcim/forms/filtersets.py:2024
#: netbox/dcim/forms/filtersets.py:2048 netbox/dcim/forms/model_forms.py:728
#: netbox/dcim/forms/model_forms.py:943 netbox/dcim/forms/model_forms.py:1355
#: netbox/dcim/forms/model_forms.py:1849 netbox/dcim/forms/model_forms.py:1922
#: netbox/dcim/forms/filtersets.py:2048 netbox/dcim/forms/model_forms.py:738
#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1365
#: netbox/dcim/forms/model_forms.py:1859 netbox/dcim/forms/model_forms.py:1932
#: netbox/dcim/forms/object_create.py:205 netbox/dcim/tables/connections.py:22
#: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60
#: netbox/dcim/tables/devices.py:291 netbox/dcim/tables/devices.py:386
@@ -2260,7 +2260,7 @@ msgstr ""
#: netbox/core/forms/filtersets.py:133 netbox/core/forms/filtersets.py:162
#: netbox/dcim/forms/bulk_edit.py:455 netbox/dcim/forms/filtersets.py:504
#: netbox/dcim/forms/model_forms.py:324 netbox/extras/forms/filtersets.py:608
#: netbox/dcim/forms/model_forms.py:326 netbox/extras/forms/filtersets.py:608
#: netbox/extras/forms/filtersets.py:628 netbox/extras/tables/tables.py:391
#: netbox/extras/tables/tables.py:431
#: netbox/templates/core/objectchange.html:36
@@ -3082,10 +3082,10 @@ msgstr ""
#: netbox/dcim/forms/bulk_import.py:658 netbox/dcim/forms/bulk_import.py:935
#: netbox/dcim/forms/bulk_import.py:1205 netbox/dcim/forms/filtersets.py:263
#: netbox/dcim/forms/filtersets.py:768 netbox/dcim/forms/filtersets.py:783
#: netbox/dcim/forms/model_forms.py:81 netbox/dcim/forms/model_forms.py:99
#: netbox/dcim/forms/model_forms.py:176 netbox/dcim/forms/model_forms.py:502
#: netbox/dcim/forms/model_forms.py:523 netbox/dcim/forms/model_forms.py:1206
#: netbox/dcim/forms/model_forms.py:1689 netbox/dcim/forms/object_import.py:177
#: netbox/dcim/forms/model_forms.py:83 netbox/dcim/forms/model_forms.py:101
#: netbox/dcim/forms/model_forms.py:178 netbox/dcim/forms/model_forms.py:504
#: netbox/dcim/forms/model_forms.py:525 netbox/dcim/forms/model_forms.py:1216
#: netbox/dcim/forms/model_forms.py:1699 netbox/dcim/forms/object_import.py:177
#: netbox/dcim/tables/devices.py:702 netbox/dcim/tables/devices.py:916
#: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devices.py:1156
#: netbox/ipam/forms/bulk_import.py:578 netbox/ipam/forms/model_forms.py:755
@@ -3216,8 +3216,8 @@ msgstr ""
#: netbox/dcim/choices.py:885 netbox/dcim/choices.py:1351
#: netbox/dcim/forms/bulk_edit.py:1543 netbox/dcim/forms/filtersets.py:1553
#: netbox/dcim/forms/filtersets.py:1678 netbox/dcim/forms/model_forms.py:1105
#: netbox/dcim/forms/model_forms.py:1569 netbox/netbox/navigation/menu.py:147
#: netbox/dcim/forms/filtersets.py:1678 netbox/dcim/forms/model_forms.py:1115
#: netbox/dcim/forms/model_forms.py:1579 netbox/netbox/navigation/menu.py:147
#: netbox/netbox/navigation/menu.py:151
#: netbox/templates/dcim/interface.html:280
msgid "Wireless"
@@ -3228,7 +3228,7 @@ msgid "Virtual interfaces"
msgstr ""
#: netbox/dcim/choices.py:1152 netbox/dcim/forms/bulk_edit.py:1396
#: netbox/dcim/forms/bulk_import.py:942 netbox/dcim/forms/model_forms.py:1087
#: netbox/dcim/forms/bulk_import.py:942 netbox/dcim/forms/model_forms.py:1097
#: netbox/dcim/tables/devices.py:706 netbox/templates/dcim/interface.html:112
#: netbox/templates/virtualization/vminterface.html:43
#: netbox/virtualization/forms/bulk_edit.py:177
@@ -3835,7 +3835,7 @@ msgstr ""
#: netbox/dcim/filtersets.py:1242 netbox/dcim/forms/filtersets.py:906
#: netbox/dcim/forms/filtersets.py:1609 netbox/dcim/forms/filtersets.py:1947
#: netbox/dcim/forms/model_forms.py:1895 netbox/dcim/models/devices.py:1307
#: netbox/dcim/forms/model_forms.py:1905 netbox/dcim/models/devices.py:1307
#: netbox/dcim/models/devices.py:1330 netbox/virtualization/filtersets.py:211
#: netbox/virtualization/filtersets.py:284
#: netbox/virtualization/forms/filtersets.py:187
@@ -4001,7 +4001,7 @@ msgstr ""
#: netbox/dcim/filtersets.py:1942 netbox/dcim/forms/bulk_edit.py:1509
#: netbox/dcim/forms/bulk_import.py:1027 netbox/dcim/forms/filtersets.py:1662
#: netbox/dcim/forms/model_forms.py:1535
#: netbox/dcim/forms/model_forms.py:1545
#: netbox/dcim/models/device_components.py:866
#: netbox/dcim/tables/devices.py:660 netbox/ipam/filtersets.py:345
#: netbox/ipam/filtersets.py:356 netbox/ipam/filtersets.py:489
@@ -4060,7 +4060,7 @@ msgid "VLAN Translation Policy (ID)"
msgstr ""
#: netbox/dcim/filtersets.py:1970 netbox/dcim/forms/filtersets.py:1633
#: netbox/dcim/forms/model_forms.py:1552
#: netbox/dcim/forms/model_forms.py:1562
#: netbox/dcim/models/device_components.py:668
#: netbox/ipam/forms/filtersets.py:518 netbox/ipam/forms/model_forms.py:700
#: netbox/templates/ipam/vlantranslationpolicy.html:11
@@ -4114,14 +4114,14 @@ msgstr ""
msgid "Primary MAC address (ID)"
msgstr ""
#: netbox/dcim/filtersets.py:2057 netbox/dcim/forms/model_forms.py:1539
#: netbox/dcim/filtersets.py:2057 netbox/dcim/forms/model_forms.py:1549
#: netbox/virtualization/filtersets.py:295
#: netbox/virtualization/forms/model_forms.py:302
msgid "Primary MAC address"
msgstr ""
#: netbox/dcim/filtersets.py:2079 netbox/dcim/filtersets.py:2091
#: netbox/dcim/forms/filtersets.py:1569 netbox/dcim/forms/model_forms.py:1875
#: netbox/dcim/forms/filtersets.py:1569 netbox/dcim/forms/model_forms.py:1885
#: netbox/templates/dcim/virtualdevicecontext.html:15
msgid "Virtual Device Context"
msgstr ""
@@ -4189,8 +4189,8 @@ msgid "Tags"
msgstr ""
#: netbox/dcim/forms/bulk_create.py:115 netbox/dcim/forms/filtersets.py:1814
#: netbox/dcim/forms/filtersets.py:1827 netbox/dcim/forms/model_forms.py:583
#: netbox/dcim/forms/model_forms.py:641 netbox/dcim/forms/object_create.py:153
#: netbox/dcim/forms/filtersets.py:1827 netbox/dcim/forms/model_forms.py:585
#: netbox/dcim/forms/model_forms.py:651 netbox/dcim/forms/object_create.py:153
#: netbox/dcim/forms/object_create.py:254 netbox/dcim/tables/devices.py:167
#: netbox/templates/dcim/frontport.html:132
#: netbox/templates/dcim/modulebay.html:38
@@ -4225,7 +4225,7 @@ msgid "Contact E-mail"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:149 netbox/dcim/forms/bulk_import.py:130
#: netbox/dcim/forms/model_forms.py:135
#: netbox/dcim/forms/model_forms.py:137
msgid "Time zone"
msgstr ""
@@ -4240,10 +4240,10 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:537 netbox/dcim/forms/filtersets.py:684
#: netbox/dcim/forms/filtersets.py:788 netbox/dcim/forms/filtersets.py:870
#: netbox/dcim/forms/filtersets.py:1080 netbox/dcim/forms/filtersets.py:1877
#: netbox/dcim/forms/filtersets.py:1917 netbox/dcim/forms/model_forms.py:211
#: netbox/dcim/forms/model_forms.py:342 netbox/dcim/forms/model_forms.py:354
#: netbox/dcim/forms/model_forms.py:424 netbox/dcim/forms/model_forms.py:528
#: netbox/dcim/forms/model_forms.py:1219 netbox/dcim/forms/model_forms.py:1702
#: netbox/dcim/forms/filtersets.py:1917 netbox/dcim/forms/model_forms.py:213
#: netbox/dcim/forms/model_forms.py:344 netbox/dcim/forms/model_forms.py:356
#: netbox/dcim/forms/model_forms.py:426 netbox/dcim/forms/model_forms.py:530
#: netbox/dcim/forms/model_forms.py:1229 netbox/dcim/forms/model_forms.py:1712
#: netbox/dcim/forms/object_import.py:188 netbox/dcim/tables/devices.py:99
#: netbox/dcim/tables/devices.py:174 netbox/dcim/tables/devices.py:986
#: netbox/dcim/tables/devicetypes.py:86 netbox/dcim/tables/devicetypes.py:321
@@ -4310,7 +4310,7 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:438
#: netbox/dcim/forms/filtersets.py:531 netbox/dcim/forms/filtersets.py:642
#: netbox/dcim/forms/filtersets.py:673 netbox/dcim/forms/filtersets.py:744
#: netbox/dcim/forms/model_forms.py:225 netbox/dcim/forms/model_forms.py:306
#: netbox/dcim/forms/model_forms.py:227 netbox/dcim/forms/model_forms.py:308
#: netbox/dcim/tables/devicetypes.py:109 netbox/dcim/tables/modules.py:54
#: netbox/dcim/tables/racks.py:70 netbox/dcim/tables/racks.py:161
#: netbox/dcim/views.py:880 netbox/dcim/views.py:1007
@@ -4343,17 +4343,17 @@ msgid "Weight unit"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:287 netbox/dcim/forms/filtersets.py:332
#: netbox/dcim/forms/model_forms.py:221 netbox/dcim/forms/model_forms.py:260
#: netbox/dcim/forms/model_forms.py:223 netbox/dcim/forms/model_forms.py:262
msgid "Rack Type"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:437
#: netbox/dcim/forms/model_forms.py:224 netbox/dcim/forms/model_forms.py:305
#: netbox/dcim/forms/model_forms.py:226 netbox/dcim/forms/model_forms.py:307
msgid "Outer Dimensions"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:292 netbox/dcim/forms/model_forms.py:226
#: netbox/dcim/forms/model_forms.py:307 netbox/dcim/ui/panels.py:126
#: netbox/dcim/forms/bulk_edit.py:292 netbox/dcim/forms/model_forms.py:228
#: netbox/dcim/forms/model_forms.py:309 netbox/dcim/ui/panels.py:126
#: netbox/dcim/views.py:874 netbox/dcim/views.py:1005
#: netbox/extras/tables/tables.py:266
#: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3
@@ -4362,7 +4362,7 @@ msgid "Dimensions"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:294 netbox/dcim/forms/filtersets.py:333
#: netbox/dcim/forms/filtersets.py:358 netbox/dcim/forms/model_forms.py:228
#: netbox/dcim/forms/filtersets.py:358 netbox/dcim/forms/model_forms.py:230
#: netbox/dcim/views.py:879 netbox/dcim/views.py:1006
#: netbox/templates/dcim/inc/panels/racktype_numbering.html:3
msgid "Numbering"
@@ -4403,8 +4403,8 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:456 netbox/dcim/forms/filtersets.py:494
#: netbox/dcim/forms/filtersets.py:860 netbox/dcim/forms/filtersets.py:1070
#: netbox/dcim/forms/filtersets.py:1168 netbox/dcim/forms/filtersets.py:1305
#: netbox/dcim/forms/model_forms.py:270 netbox/dcim/forms/model_forms.py:314
#: netbox/dcim/forms/model_forms.py:574 netbox/dcim/forms/model_forms.py:851
#: netbox/dcim/forms/model_forms.py:272 netbox/dcim/forms/model_forms.py:316
#: netbox/dcim/forms/model_forms.py:576 netbox/dcim/forms/model_forms.py:861
#: netbox/dcim/forms/object_create.py:301 netbox/dcim/tables/devices.py:163
#: netbox/dcim/tables/power.py:66 netbox/dcim/tables/racks.py:203
#: netbox/ipam/forms/filtersets.py:474
@@ -4419,14 +4419,14 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:357 netbox/dcim/forms/filtersets.py:435
#: netbox/dcim/forms/filtersets.py:524 netbox/dcim/forms/filtersets.py:667
#: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:1028
#: netbox/dcim/forms/model_forms.py:432 netbox/dcim/forms/model_forms.py:767
#: netbox/dcim/forms/model_forms.py:1770
#: netbox/dcim/forms/model_forms.py:434 netbox/dcim/forms/model_forms.py:777
#: netbox/dcim/forms/model_forms.py:1780
#: netbox/templates/dcim/device_edit.html:22
msgid "Hardware"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:487 netbox/dcim/forms/bulk_import.py:414
#: netbox/dcim/forms/filtersets.py:542 netbox/dcim/forms/model_forms.py:359
#: netbox/dcim/forms/filtersets.py:542 netbox/dcim/forms/model_forms.py:361
msgid "Default platform"
msgstr ""
@@ -4443,17 +4443,17 @@ msgstr ""
msgid "Exclude from utilization"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:531 netbox/dcim/forms/model_forms.py:373
#: netbox/dcim/forms/model_forms.py:1002 netbox/dcim/forms/model_forms.py:1044
#: netbox/dcim/forms/model_forms.py:1071 netbox/dcim/forms/model_forms.py:1099
#: netbox/dcim/forms/model_forms.py:1120 netbox/dcim/forms/model_forms.py:1160
#: netbox/dcim/forms/model_forms.py:1178 netbox/dcim/forms/object_create.py:117
#: netbox/dcim/forms/bulk_edit.py:531 netbox/dcim/forms/model_forms.py:375
#: netbox/dcim/forms/model_forms.py:1012 netbox/dcim/forms/model_forms.py:1054
#: netbox/dcim/forms/model_forms.py:1081 netbox/dcim/forms/model_forms.py:1109
#: netbox/dcim/forms/model_forms.py:1130 netbox/dcim/forms/model_forms.py:1170
#: netbox/dcim/forms/model_forms.py:1188 netbox/dcim/forms/object_create.py:117
#: netbox/dcim/tables/devicetypes.py:83 netbox/templates/dcim/devicebay.html:52
#: netbox/templates/dcim/module.html:61
msgid "Device Type"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/model_forms.py:400
#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/model_forms.py:402
#: netbox/dcim/views.py:1578 netbox/extras/forms/model_forms.py:588
msgid "Schema"
msgstr ""
@@ -4461,8 +4461,8 @@ msgstr ""
#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:553
#: netbox/dcim/forms/bulk_edit.py:784 netbox/dcim/forms/bulk_import.py:452
#: netbox/dcim/forms/bulk_import.py:1452 netbox/dcim/forms/filtersets.py:679
#: netbox/dcim/forms/filtersets.py:1197 netbox/dcim/forms/model_forms.py:406
#: netbox/dcim/forms/model_forms.py:419 netbox/dcim/tables/modules.py:42
#: netbox/dcim/forms/filtersets.py:1197 netbox/dcim/forms/model_forms.py:408
#: netbox/dcim/forms/model_forms.py:421 netbox/dcim/tables/modules.py:42
#: netbox/extras/forms/filtersets.py:437 netbox/extras/forms/model_forms.py:613
#: netbox/extras/tables/tables.py:615 netbox/templates/account/base.html:7
#: netbox/templates/dcim/cable.html:23 netbox/templates/dcim/moduletype.html:27
@@ -4473,10 +4473,10 @@ msgid "Profile"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:585 netbox/dcim/forms/filtersets.py:1359
#: netbox/dcim/forms/model_forms.py:431 netbox/dcim/forms/model_forms.py:1003
#: netbox/dcim/forms/model_forms.py:1045 netbox/dcim/forms/model_forms.py:1072
#: netbox/dcim/forms/model_forms.py:1100 netbox/dcim/forms/model_forms.py:1121
#: netbox/dcim/forms/model_forms.py:1161 netbox/dcim/forms/model_forms.py:1179
#: netbox/dcim/forms/model_forms.py:433 netbox/dcim/forms/model_forms.py:1013
#: netbox/dcim/forms/model_forms.py:1055 netbox/dcim/forms/model_forms.py:1082
#: netbox/dcim/forms/model_forms.py:1110 netbox/dcim/forms/model_forms.py:1131
#: netbox/dcim/forms/model_forms.py:1171 netbox/dcim/forms/model_forms.py:1189
#: netbox/dcim/forms/object_create.py:118 netbox/dcim/tables/modules.py:51
#: netbox/dcim/tables/modules.py:94 netbox/templates/dcim/module.html:92
#: netbox/templates/dcim/modulebay.html:66
@@ -4484,7 +4484,7 @@ msgstr ""
msgid "Module Type"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:589 netbox/dcim/forms/model_forms.py:376
#: netbox/dcim/forms/bulk_edit.py:589 netbox/dcim/forms/model_forms.py:378
msgid "Chassis"
msgstr ""
@@ -4499,8 +4499,8 @@ msgstr ""
#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:678
#: netbox/dcim/forms/bulk_import.py:682 netbox/dcim/forms/filtersets.py:763
#: netbox/dcim/forms/filtersets.py:793 netbox/dcim/forms/filtersets.py:911
#: netbox/dcim/forms/model_forms.py:497 netbox/dcim/forms/model_forms.py:534
#: netbox/dcim/forms/model_forms.py:650
#: netbox/dcim/forms/model_forms.py:499 netbox/dcim/forms/model_forms.py:536
#: netbox/dcim/forms/model_forms.py:660
#: netbox/virtualization/forms/bulk_import.py:146
#: netbox/virtualization/forms/bulk_import.py:147
#: netbox/virtualization/forms/filtersets.py:203
@@ -4510,20 +4510,20 @@ msgstr ""
#: netbox/dcim/forms/bulk_edit.py:654 netbox/dcim/forms/bulk_edit.py:1037
#: netbox/dcim/forms/bulk_import.py:584 netbox/dcim/forms/filtersets.py:130
#: netbox/dcim/forms/filtersets.py:1350 netbox/dcim/forms/model_forms.py:596
#: netbox/dcim/forms/model_forms.py:966 netbox/dcim/forms/model_forms.py:983
#: netbox/dcim/forms/filtersets.py:1350 netbox/dcim/forms/model_forms.py:606
#: netbox/dcim/forms/model_forms.py:976 netbox/dcim/forms/model_forms.py:993
#: netbox/extras/filtersets.py:703
msgid "Device type"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:665 netbox/dcim/forms/bulk_import.py:565
#: netbox/dcim/forms/filtersets.py:135 netbox/dcim/forms/model_forms.py:604
#: netbox/dcim/forms/filtersets.py:135 netbox/dcim/forms/model_forms.py:614
msgid "Device role"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:688 netbox/dcim/forms/bulk_import.py:590
#: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:884
#: netbox/dcim/forms/model_forms.py:545 netbox/dcim/forms/model_forms.py:609
#: netbox/dcim/forms/model_forms.py:547 netbox/dcim/forms/model_forms.py:619
#: netbox/dcim/tables/devices.py:189 netbox/extras/filtersets.py:719
#: netbox/templates/dcim/platform.html:26
#: netbox/templates/virtualization/virtualmachine.html:31
@@ -4537,7 +4537,7 @@ msgstr ""
#: netbox/dcim/forms/bulk_edit.py:713 netbox/dcim/forms/bulk_import.py:609
#: netbox/dcim/forms/filtersets.py:816 netbox/dcim/forms/filtersets.py:986
#: netbox/dcim/forms/model_forms.py:618 netbox/dcim/tables/devices.py:209
#: netbox/dcim/forms/model_forms.py:628 netbox/dcim/tables/devices.py:209
#: netbox/extras/filtersets.py:752 netbox/extras/forms/filtersets.py:431
#: netbox/ipam/forms/filtersets.py:446 netbox/ipam/forms/filtersets.py:479
#: netbox/templates/virtualization/cluster.html:10
@@ -4568,7 +4568,7 @@ msgid "Virtualization"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:741 netbox/dcim/forms/bulk_import.py:751
#: netbox/dcim/forms/model_forms.py:745 netbox/dcim/forms/model_forms.py:991
#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/model_forms.py:1001
msgid "Module type"
msgstr ""
@@ -4611,7 +4611,7 @@ msgid "Domain"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:883 netbox/dcim/forms/bulk_import.py:1636
#: netbox/dcim/forms/filtersets.py:1296 netbox/dcim/forms/model_forms.py:845
#: netbox/dcim/forms/filtersets.py:1296 netbox/dcim/forms/model_forms.py:855
msgid "Power panel"
msgstr ""
@@ -4660,8 +4660,8 @@ msgid "Allocated power draw (watts)"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1058 netbox/dcim/forms/bulk_import.py:885
#: netbox/dcim/forms/model_forms.py:1060 netbox/dcim/forms/model_forms.py:1425
#: netbox/dcim/forms/model_forms.py:1754 netbox/dcim/forms/object_import.py:56
#: netbox/dcim/forms/model_forms.py:1070 netbox/dcim/forms/model_forms.py:1435
#: netbox/dcim/forms/model_forms.py:1764 netbox/dcim/forms/object_import.py:56
msgid "Power port"
msgstr ""
@@ -4695,8 +4695,8 @@ msgstr ""
msgid "Wireless role"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/model_forms.py:766
#: netbox/dcim/forms/model_forms.py:1370 netbox/dcim/tables/devices.py:328
#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/model_forms.py:776
#: netbox/dcim/forms/model_forms.py:1380 netbox/dcim/tables/devices.py:328
#: netbox/templates/dcim/consoleport.html:24
#: netbox/templates/dcim/consoleserverport.html:24
#: netbox/templates/dcim/frontport.html:24
@@ -4714,7 +4714,7 @@ msgstr ""
msgid "LAG"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/model_forms.py:1452
#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/model_forms.py:1462
msgid "Virtual device contexts"
msgstr ""
@@ -4743,7 +4743,7 @@ msgid "Mode"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1458 netbox/dcim/forms/bulk_import.py:993
#: netbox/dcim/forms/model_forms.py:1501 netbox/ipam/forms/bulk_import.py:173
#: netbox/dcim/forms/model_forms.py:1511 netbox/ipam/forms/bulk_import.py:173
#: netbox/ipam/forms/filtersets.py:568 netbox/ipam/models/vlans.py:93
#: netbox/virtualization/forms/bulk_edit.py:205
#: netbox/virtualization/forms/bulk_import.py:185
@@ -4752,7 +4752,7 @@ msgid "VLAN group"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1467 netbox/dcim/forms/bulk_import.py:1000
#: netbox/dcim/forms/model_forms.py:1507 netbox/dcim/tables/devices.py:605
#: netbox/dcim/forms/model_forms.py:1517 netbox/dcim/tables/devices.py:605
#: netbox/virtualization/forms/bulk_edit.py:213
#: netbox/virtualization/forms/bulk_import.py:192
#: netbox/virtualization/forms/model_forms.py:331
@@ -4760,7 +4760,7 @@ msgid "Untagged VLAN"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/bulk_import.py:1007
#: netbox/dcim/forms/model_forms.py:1516 netbox/dcim/tables/devices.py:611
#: netbox/dcim/forms/model_forms.py:1526 netbox/dcim/tables/devices.py:611
#: netbox/virtualization/forms/bulk_edit.py:221
#: netbox/virtualization/forms/bulk_import.py:199
#: netbox/virtualization/forms/model_forms.py:340
@@ -4776,18 +4776,18 @@ msgid "Remove tagged VLANs"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/bulk_import.py:1020
#: netbox/dcim/forms/model_forms.py:1525
#: netbox/dcim/forms/model_forms.py:1535
#: netbox/virtualization/forms/bulk_import.py:212
#: netbox/virtualization/forms/model_forms.py:349
msgid "Q-in-Q Service VLAN"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1514 netbox/dcim/forms/model_forms.py:1488
#: netbox/dcim/forms/bulk_edit.py:1514 netbox/dcim/forms/model_forms.py:1498
#: netbox/wireless/forms/filtersets.py:26
msgid "Wireless LAN group"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1519 netbox/dcim/forms/model_forms.py:1493
#: netbox/dcim/forms/bulk_edit.py:1519 netbox/dcim/forms/model_forms.py:1503
#: netbox/dcim/tables/devices.py:653 netbox/netbox/navigation/menu.py:153
#: netbox/templates/dcim/interface.html:350
#: netbox/wireless/tables/wirelesslan.py:20
@@ -4795,7 +4795,7 @@ msgid "Wireless LANs"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1528 netbox/dcim/forms/filtersets.py:1550
#: netbox/dcim/forms/model_forms.py:1559 netbox/ipam/forms/bulk_edit.py:224
#: netbox/dcim/forms/model_forms.py:1569 netbox/ipam/forms/bulk_edit.py:224
#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/filtersets.py:184
#: netbox/netbox/navigation/menu.py:109
#: netbox/templates/dcim/interface.html:141
@@ -4807,18 +4807,18 @@ msgid "Addressing"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1529 netbox/dcim/forms/filtersets.py:808
#: netbox/dcim/forms/model_forms.py:1560
#: netbox/dcim/forms/model_forms.py:1570
#: netbox/virtualization/forms/model_forms.py:370
msgid "Operation"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1530 netbox/dcim/forms/filtersets.py:1551
#: netbox/dcim/forms/filtersets.py:1677 netbox/dcim/forms/model_forms.py:1104
#: netbox/dcim/forms/model_forms.py:1562
#: netbox/dcim/forms/filtersets.py:1677 netbox/dcim/forms/model_forms.py:1114
#: netbox/dcim/forms/model_forms.py:1572
msgid "PoE"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1531 netbox/dcim/forms/model_forms.py:1561
#: netbox/dcim/forms/bulk_edit.py:1531 netbox/dcim/forms/model_forms.py:1571
#: netbox/templates/dcim/interface.html:105
#: netbox/virtualization/forms/bulk_edit.py:237
#: netbox/virtualization/forms/model_forms.py:371
@@ -4826,7 +4826,7 @@ msgid "Related Interfaces"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1533 netbox/dcim/forms/filtersets.py:1552
#: netbox/dcim/forms/model_forms.py:1565
#: netbox/dcim/forms/model_forms.py:1575
#: netbox/virtualization/forms/bulk_edit.py:240
#: netbox/virtualization/forms/filtersets.py:215
#: netbox/virtualization/forms/model_forms.py:374
@@ -4934,7 +4934,7 @@ msgstr ""
msgid "Rack's location (if any)"
msgstr ""
#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/model_forms.py:319
#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/model_forms.py:321
#: netbox/dcim/tables/racks.py:208 netbox/templates/dcim/rackreservation.html:7
msgid "Units"
msgstr ""
@@ -5014,7 +5014,7 @@ msgid "Assigned platform"
msgstr ""
#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/bulk_import.py:606
#: netbox/dcim/forms/model_forms.py:631
#: netbox/dcim/forms/model_forms.py:641
msgid "Virtual chassis"
msgstr ""
@@ -5030,7 +5030,7 @@ msgstr ""
msgid "Assigned rack (if any)"
msgstr ""
#: netbox/dcim/forms/bulk_import.py:652
#: netbox/dcim/forms/bulk_import.py:652 netbox/dcim/forms/model_forms.py:598
msgid "Face"
msgstr ""
@@ -5054,7 +5054,7 @@ msgstr ""
msgid "The device in which this module is installed"
msgstr ""
#: netbox/dcim/forms/bulk_import.py:745 netbox/dcim/forms/model_forms.py:735
#: netbox/dcim/forms/bulk_import.py:745 netbox/dcim/forms/model_forms.py:745
msgid "Module bay"
msgstr ""
@@ -5066,7 +5066,7 @@ msgstr ""
msgid "The type of module"
msgstr ""
#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/model_forms.py:753
#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/model_forms.py:763
msgid "Replicate components"
msgstr ""
@@ -5076,11 +5076,11 @@ msgid ""
"by default)"
msgstr ""
#: netbox/dcim/forms/bulk_import.py:767 netbox/dcim/forms/model_forms.py:759
#: netbox/dcim/forms/bulk_import.py:767 netbox/dcim/forms/model_forms.py:769
msgid "Adopt components"
msgstr ""
#: netbox/dcim/forms/bulk_import.py:769 netbox/dcim/forms/model_forms.py:762
#: netbox/dcim/forms/bulk_import.py:769 netbox/dcim/forms/model_forms.py:772
msgid "Adopt already existing components"
msgstr ""
@@ -5105,13 +5105,13 @@ msgstr ""
msgid "Electrical phase (for three-phase circuits)"
msgstr ""
#: netbox/dcim/forms/bulk_import.py:939 netbox/dcim/forms/model_forms.py:1463
#: netbox/dcim/forms/bulk_import.py:939 netbox/dcim/forms/model_forms.py:1473
#: netbox/virtualization/forms/bulk_import.py:169
#: netbox/virtualization/forms/model_forms.py:310
msgid "Parent interface"
msgstr ""
#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/model_forms.py:1471
#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/model_forms.py:1481
#: netbox/virtualization/forms/bulk_import.py:176
#: netbox/virtualization/forms/model_forms.py:318
msgid "Bridged interface"
@@ -5362,7 +5362,7 @@ msgid ""
"characters: invalid hex."
msgstr ""
#: netbox/dcim/forms/bulk_import.py:1584 netbox/dcim/forms/model_forms.py:880
#: netbox/dcim/forms/bulk_import.py:1584 netbox/dcim/forms/model_forms.py:890
#: netbox/dcim/tables/devices.py:1075
#: netbox/templates/dcim/panels/virtual_chassis_members.html:10
#: netbox/templates/dcim/virtualchassis.html:17
@@ -5394,7 +5394,7 @@ msgstr ""
msgid "Single or three-phase"
msgstr ""
#: netbox/dcim/forms/bulk_import.py:1729 netbox/dcim/forms/model_forms.py:1855
#: netbox/dcim/forms/bulk_import.py:1729 netbox/dcim/forms/model_forms.py:1865
#: netbox/dcim/ui/panels.py:109
#: netbox/templates/dcim/virtualdevicecontext.html:30
#: netbox/templates/virtualization/virtualmachine.html:56
@@ -5405,7 +5405,7 @@ msgstr ""
msgid "IPv4 address with mask, e.g. 1.2.3.4/24"
msgstr ""
#: netbox/dcim/forms/bulk_import.py:1736 netbox/dcim/forms/model_forms.py:1864
#: netbox/dcim/forms/bulk_import.py:1736 netbox/dcim/forms/model_forms.py:1874
#: netbox/dcim/ui/panels.py:114
#: netbox/templates/dcim/virtualdevicecontext.html:41
#: netbox/templates/virtualization/virtualmachine.html:72
@@ -5453,7 +5453,7 @@ msgstr ""
msgid "A {model} named {name} already exists"
msgstr ""
#: netbox/dcim/forms/connections.py:54 netbox/dcim/forms/model_forms.py:833
#: netbox/dcim/forms/connections.py:54 netbox/dcim/forms/model_forms.py:843
#: netbox/dcim/tables/power.py:62
#: netbox/templates/dcim/inc/cable_termination.html:40
#: netbox/templates/dcim/powerfeed.html:24
@@ -5462,7 +5462,7 @@ msgstr ""
msgid "Power Panel"
msgstr ""
#: netbox/dcim/forms/connections.py:63 netbox/dcim/forms/model_forms.py:860
#: netbox/dcim/forms/connections.py:63 netbox/dcim/forms/model_forms.py:870
#: netbox/templates/dcim/powerfeed.html:21
#: netbox/templates/dcim/powerport.html:80
msgid "Power Feed"
@@ -5517,12 +5517,12 @@ msgstr ""
msgid "Function"
msgstr ""
#: netbox/dcim/forms/filtersets.py:455 netbox/dcim/forms/model_forms.py:329
#: netbox/dcim/forms/filtersets.py:455 netbox/dcim/forms/model_forms.py:331
#: netbox/dcim/tables/racks.py:188 netbox/dcim/views.py:1152
msgid "Reservation"
msgstr ""
#: netbox/dcim/forms/filtersets.py:526 netbox/dcim/forms/model_forms.py:378
#: netbox/dcim/forms/filtersets.py:526 netbox/dcim/forms/model_forms.py:380
#: netbox/netbox/views/generic/feature_views.py:97
#: netbox/templates/inc/panels/image_attachments.html:6
msgid "Images"
@@ -5545,7 +5545,7 @@ msgstr ""
msgid "Module count"
msgstr ""
#: netbox/dcim/forms/filtersets.py:758 netbox/dcim/forms/model_forms.py:510
#: netbox/dcim/forms/filtersets.py:758 netbox/dcim/forms/model_forms.py:512
#: netbox/templates/dcim/devicerole.html:23
msgid "Device Role"
msgstr ""
@@ -5608,7 +5608,7 @@ msgstr ""
msgid "Mgmt only"
msgstr ""
#: netbox/dcim/forms/filtersets.py:1613 netbox/dcim/forms/model_forms.py:1547
#: netbox/dcim/forms/filtersets.py:1613 netbox/dcim/forms/model_forms.py:1557
#: netbox/dcim/models/device_components.py:791
#: netbox/templates/dcim/interface.html:155
msgid "WWN"
@@ -5716,63 +5716,63 @@ msgid ""
"selected number of rear port positions ({rearport_count})."
msgstr ""
#: netbox/dcim/forms/model_forms.py:146
#: netbox/dcim/forms/model_forms.py:148
msgid "Contact Info"
msgstr ""
#: netbox/dcim/forms/model_forms.py:199
#: netbox/dcim/forms/model_forms.py:201
msgid "Rack Role"
msgstr ""
#: netbox/dcim/forms/model_forms.py:216 netbox/dcim/forms/model_forms.py:368
#: netbox/dcim/forms/model_forms.py:539
#: netbox/dcim/forms/model_forms.py:218 netbox/dcim/forms/model_forms.py:370
#: netbox/dcim/forms/model_forms.py:541
#: netbox/utilities/forms/fields/fields.py:57
msgid "Slug"
msgstr ""
#: netbox/dcim/forms/model_forms.py:264
#: netbox/dcim/forms/model_forms.py:266
msgid "Select a pre-defined rack type, or set physical characteristics below."
msgstr ""
#: netbox/dcim/forms/model_forms.py:272
#: netbox/dcim/forms/model_forms.py:274
msgid "Inventory Control"
msgstr ""
#: netbox/dcim/forms/model_forms.py:321
#: netbox/dcim/forms/model_forms.py:323
msgid ""
"Comma-separated list of numeric unit IDs. A range may be specified using a "
"hyphen."
msgstr ""
#: netbox/dcim/forms/model_forms.py:402 netbox/extras/forms/model_forms.py:590
#: netbox/dcim/forms/model_forms.py:404 netbox/extras/forms/model_forms.py:590
msgid "Enter a valid JSON schema to define supported attributes."
msgstr ""
#: netbox/dcim/forms/model_forms.py:433
#: netbox/dcim/forms/model_forms.py:435
msgid "Profile & Attributes"
msgstr ""
#: netbox/dcim/forms/model_forms.py:585 netbox/dcim/models/devices.py:572
#: netbox/dcim/forms/model_forms.py:587 netbox/dcim/models/devices.py:572
msgid "The lowest-numbered unit occupied by the device"
msgstr ""
#: netbox/dcim/forms/model_forms.py:642
#: netbox/dcim/forms/model_forms.py:652
msgid "The position in the virtual chassis this device is identified by"
msgstr ""
#: netbox/dcim/forms/model_forms.py:647
#: netbox/dcim/forms/model_forms.py:657
msgid "The priority of the device in the virtual chassis"
msgstr ""
#: netbox/dcim/forms/model_forms.py:756
#: netbox/dcim/forms/model_forms.py:766
msgid "Automatically populate components associated with this module type"
msgstr ""
#: netbox/dcim/forms/model_forms.py:862
#: netbox/dcim/forms/model_forms.py:872
msgid "Characteristics"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1018
#: netbox/dcim/forms/model_forms.py:1028
#, python-brace-format
msgid ""
"Alphanumeric ranges are supported for bulk creation. Mixed cases and types "
@@ -5781,35 +5781,35 @@ msgid ""
"replaced with the position value when creating a new module."
msgstr ""
#: netbox/dcim/forms/model_forms.py:1231
#: netbox/dcim/forms/model_forms.py:1241
msgid "Console port template"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1239
#: netbox/dcim/forms/model_forms.py:1249
msgid "Console server port template"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1247
#: netbox/dcim/forms/model_forms.py:1257
msgid "Front port template"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1255
#: netbox/dcim/forms/model_forms.py:1265
msgid "Interface template"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1263
#: netbox/dcim/forms/model_forms.py:1273
msgid "Power outlet template"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1271
#: netbox/dcim/forms/model_forms.py:1281
msgid "Power port template"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1279
#: netbox/dcim/forms/model_forms.py:1289
msgid "Rear port template"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1289 netbox/dcim/forms/model_forms.py:1774
#: netbox/dcim/forms/model_forms.py:1299 netbox/dcim/forms/model_forms.py:1784
#: netbox/dcim/tables/connections.py:27
#: netbox/templates/dcim/consoleport.html:17
#: netbox/templates/dcim/consoleserverport.html:73
@@ -5817,14 +5817,14 @@ msgstr ""
msgid "Console Port"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1290 netbox/dcim/forms/model_forms.py:1775
#: netbox/dcim/forms/model_forms.py:1300 netbox/dcim/forms/model_forms.py:1785
#: netbox/templates/dcim/consoleport.html:73
#: netbox/templates/dcim/consoleserverport.html:17
#: netbox/templates/dcim/frontport.html:106
msgid "Console Server Port"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1291 netbox/dcim/forms/model_forms.py:1776
#: netbox/dcim/forms/model_forms.py:1301 netbox/dcim/forms/model_forms.py:1786
#: netbox/templates/circuits/inc/circuit_termination_fields.html:53
#: netbox/templates/dcim/consoleport.html:76
#: netbox/templates/dcim/consoleserverport.html:76
@@ -5836,7 +5836,7 @@ msgstr ""
msgid "Front Port"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1292 netbox/dcim/forms/model_forms.py:1777
#: netbox/dcim/forms/model_forms.py:1302 netbox/dcim/forms/model_forms.py:1787
#: netbox/templates/circuits/inc/circuit_termination_fields.html:54
#: netbox/templates/dcim/consoleport.html:79
#: netbox/templates/dcim/consoleserverport.html:79
@@ -5848,80 +5848,80 @@ msgstr ""
msgid "Rear Port"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1293 netbox/dcim/forms/model_forms.py:1778
#: netbox/dcim/forms/model_forms.py:1303 netbox/dcim/forms/model_forms.py:1788
#: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:526
#: netbox/templates/dcim/poweroutlet.html:58
#: netbox/templates/dcim/powerport.html:17
msgid "Power Port"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1294 netbox/dcim/forms/model_forms.py:1779
#: netbox/dcim/forms/model_forms.py:1304 netbox/dcim/forms/model_forms.py:1789
#: netbox/templates/dcim/poweroutlet.html:17
#: netbox/templates/dcim/powerport.html:77
msgid "Power Outlet"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1296 netbox/dcim/forms/model_forms.py:1781
#: netbox/dcim/forms/model_forms.py:1306 netbox/dcim/forms/model_forms.py:1791
msgid "Component Assignment"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1342 netbox/dcim/forms/model_forms.py:1828
#: netbox/dcim/forms/model_forms.py:1352 netbox/dcim/forms/model_forms.py:1838
msgid "An InventoryItem can only be assigned to a single component."
msgstr ""
#: netbox/dcim/forms/model_forms.py:1479
#: netbox/dcim/forms/model_forms.py:1489
msgid "LAG interface"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1502
#: netbox/dcim/forms/model_forms.py:1512
msgid "Filter VLANs available for assignment by group."
msgstr ""
#: netbox/dcim/forms/model_forms.py:1671
#: netbox/dcim/forms/model_forms.py:1681
msgid "Child Device"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1672
#: netbox/dcim/forms/model_forms.py:1682
msgid ""
"Child devices must first be created and assigned to the site and rack of the "
"parent device."
msgstr ""
#: netbox/dcim/forms/model_forms.py:1714
#: netbox/dcim/forms/model_forms.py:1724
msgid "Console port"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1722
#: netbox/dcim/forms/model_forms.py:1732
msgid "Console server port"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1730 netbox/dcim/forms/object_import.py:140
#: netbox/dcim/forms/model_forms.py:1740 netbox/dcim/forms/object_import.py:140
msgid "Front port"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1746
#: netbox/dcim/forms/model_forms.py:1756
msgid "Power outlet"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1762 netbox/dcim/forms/object_import.py:145
#: netbox/dcim/forms/model_forms.py:1772 netbox/dcim/forms/object_import.py:145
msgid "Rear port"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1768
#: netbox/dcim/forms/model_forms.py:1778
#: netbox/templates/dcim/inventoryitem.html:17
msgid "Inventory Item"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1837
#: netbox/dcim/forms/model_forms.py:1847
#: netbox/templates/dcim/inventoryitemrole.html:15
msgid "Inventory Item Role"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1907
#: netbox/dcim/forms/model_forms.py:1917
msgid "VM Interface"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1923 netbox/ipam/forms/filtersets.py:638
#: netbox/dcim/forms/model_forms.py:1933 netbox/ipam/forms/filtersets.py:638
#: netbox/ipam/forms/model_forms.py:323 netbox/ipam/tables/vlans.py:171
#: netbox/templates/virtualization/virtualdisk.html:21
#: netbox/templates/virtualization/virtualmachine.html:12
@@ -5938,7 +5938,7 @@ msgstr ""
msgid "Virtual Machine"
msgstr ""
#: netbox/dcim/forms/model_forms.py:1962
#: netbox/dcim/forms/model_forms.py:1972
msgid "A MAC address can only be assigned to a single object."
msgstr ""
@@ -8460,12 +8460,12 @@ msgstr ""
msgid "Show your personal bookmarks"
msgstr ""
#: netbox/extras/events.py:164
#: netbox/extras/events.py:168
#, python-brace-format
msgid "Unknown action type for an event rule: {action_type}"
msgstr ""
#: netbox/extras/events.py:209
#: netbox/extras/events.py:213
#, python-brace-format
msgid "Cannot import events pipeline {name} error: {error}"
msgstr ""

View File

@@ -1,6 +1,6 @@
from django import template
from netbox.navigation.menu import MENUS
from netbox.navigation.menu import get_menus
__all__ = (
'nav',
@@ -19,7 +19,7 @@ def nav(context):
nav_items = []
# Construct the navigation menu based upon the current user's permissions
for menu in MENUS:
for menu in get_menus():
groups = []
for group in menu.groups:
items = []