mirror of
https://github.com/netbox-community/netbox.git
synced 2026-01-17 01:02:18 -06:00
Compare commits
21 Commits
20911-drop
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
586bc132b6 | ||
|
|
52a2b934a0 | ||
|
|
3e2a26984f | ||
|
|
f5f0c19860 | ||
|
|
8da9b11ab8 | ||
|
|
ca67fa9999 | ||
|
|
eff768192e | ||
|
|
1e297d55ee | ||
|
|
fdb987ef91 | ||
|
|
b5a23db43c | ||
|
|
366b69aff7 | ||
|
|
c3e8c5e69c | ||
|
|
b55f36469d | ||
|
|
1c46215cd5 | ||
|
|
7fded2fd87 | ||
|
|
0ddc5805c4 | ||
|
|
c1bbc026e2 | ||
|
|
8cbfe94fba | ||
|
|
fff99fd3ff | ||
|
|
f4892caa51 | ||
|
|
a54ad24b47 |
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
@@ -30,13 +30,13 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
config-file: .github/codeql/codeql-config.yml
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
@@ -44,3 +44,4 @@ class DataFileSerializer(NetBoxModelSerializer):
|
||||
'id', 'url', 'display_url', 'display', 'source', 'path', 'last_updated', 'size', 'hash',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'path')
|
||||
read_only_fields = ['path', 'last_updated', 'size', 'hash']
|
||||
|
||||
@@ -12,7 +12,7 @@ from django.core.validators import RegexValidator
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from netbox.constants import CENSOR_TOKEN, CENSOR_TOKEN_CHANGED
|
||||
from netbox.models import PrimaryModel
|
||||
@@ -128,7 +128,9 @@ class DataSource(JobsMixin, PrimaryModel):
|
||||
# Ensure URL scheme matches selected type
|
||||
if self.backend_class.is_local and self.url_scheme not in ('file', ''):
|
||||
raise ValidationError({
|
||||
'source_url': "URLs for local sources must start with file:// (or specify no scheme)"
|
||||
'source_url': _("URLs for local sources must start with {scheme} (or specify no scheme)").format(
|
||||
scheme='file://'
|
||||
)
|
||||
})
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
|
||||
@@ -140,9 +140,6 @@ class FrontPortFormMixin(forms.Form):
|
||||
widget=forms.SelectMultiple(attrs={'size': 8})
|
||||
)
|
||||
|
||||
port_mapping_model = PortMapping
|
||||
parent_field = 'device'
|
||||
|
||||
def clean(self):
|
||||
super().clean()
|
||||
|
||||
@@ -203,3 +200,22 @@ class FrontPortFormMixin(forms.Form):
|
||||
using=connection,
|
||||
update_fields=None
|
||||
)
|
||||
|
||||
def _get_rear_port_choices(self, parent_filter, front_port):
|
||||
"""
|
||||
Return a list of choices representing each available rear port & position pair on the parent object (identified
|
||||
by a Q filter), excluding those assigned to the specified instance.
|
||||
"""
|
||||
occupied_rear_port_positions = [
|
||||
f'{mapping.rear_port_id}:{mapping.rear_port_position}'
|
||||
for mapping in self.port_mapping_model.objects.filter(parent_filter).exclude(front_port=front_port.pk)
|
||||
]
|
||||
|
||||
choices = []
|
||||
for rear_port in self.rear_port_model.objects.filter(parent_filter):
|
||||
for i in range(1, rear_port.positions + 1):
|
||||
pair_id = f'{rear_port.pk}:{i}'
|
||||
if pair_id not in occupied_rear_port_positions:
|
||||
pair_label = f'{rear_port.name}:{i}'
|
||||
choices.append((pair_id, pair_label))
|
||||
return choices
|
||||
|
||||
@@ -733,10 +733,9 @@ class ModuleForm(ModuleCommonForm, PrimaryModelForm):
|
||||
)
|
||||
module_bay = DynamicModelChoiceField(
|
||||
label=_('Module bay'),
|
||||
queryset=ModuleBay.objects.order_by('name'),
|
||||
queryset=ModuleBay.objects.all(),
|
||||
query_params={
|
||||
'device_id': '$device',
|
||||
'ordering': 'name',
|
||||
'device_id': '$device'
|
||||
},
|
||||
context={
|
||||
'disabled': 'installed_module',
|
||||
@@ -1125,9 +1124,8 @@ class FrontPortTemplateForm(FrontPortFormMixin, ModularComponentTemplateForm):
|
||||
),
|
||||
)
|
||||
|
||||
# Override FrontPortFormMixin attrs
|
||||
port_mapping_model = PortTemplateMapping
|
||||
parent_field = 'device_type'
|
||||
rear_port_model = RearPortTemplate
|
||||
|
||||
class Meta:
|
||||
model = FrontPortTemplate
|
||||
@@ -1138,13 +1136,14 @@ class FrontPortTemplateForm(FrontPortFormMixin, ModularComponentTemplateForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# Populate rear port choices based on parent DeviceType or ModuleType
|
||||
if device_type_id := self.data.get('device_type') or self.initial.get('device_type'):
|
||||
device_type = DeviceType.objects.get(pk=device_type_id)
|
||||
parent_filter = Q(device_type=device_type_id)
|
||||
elif module_type_id := self.data.get('module_type') or self.initial.get('module_type'):
|
||||
parent_filter = Q(module_type=module_type_id)
|
||||
else:
|
||||
return
|
||||
|
||||
# Populate rear port choices
|
||||
self.fields['rear_ports'].choices = self._get_rear_port_choices(device_type, self.instance)
|
||||
self.fields['rear_ports'].choices = self._get_rear_port_choices(parent_filter, self.instance)
|
||||
|
||||
# Set initial rear port mappings
|
||||
if self.instance.pk:
|
||||
@@ -1153,27 +1152,6 @@ class FrontPortTemplateForm(FrontPortFormMixin, ModularComponentTemplateForm):
|
||||
for mapping in PortTemplateMapping.objects.filter(front_port_id=self.instance.pk)
|
||||
]
|
||||
|
||||
def _get_rear_port_choices(self, device_type, front_port):
|
||||
"""
|
||||
Return a list of choices representing each available rear port & position pair on the device type, excluding
|
||||
those assigned to the specified instance.
|
||||
"""
|
||||
occupied_rear_port_positions = [
|
||||
f'{mapping.rear_port_id}:{mapping.rear_port_position}'
|
||||
for mapping in device_type.port_mappings.exclude(front_port=front_port.pk)
|
||||
]
|
||||
|
||||
choices = []
|
||||
for rear_port in RearPortTemplate.objects.filter(device_type=device_type):
|
||||
for i in range(1, rear_port.positions + 1):
|
||||
pair_id = f'{rear_port.pk}:{i}'
|
||||
if pair_id not in occupied_rear_port_positions:
|
||||
pair_label = f'{rear_port.name}:{i}'
|
||||
choices.append(
|
||||
(pair_id, pair_label)
|
||||
)
|
||||
return choices
|
||||
|
||||
|
||||
class RearPortTemplateForm(ModularComponentTemplateForm):
|
||||
fieldsets = (
|
||||
@@ -1620,6 +1598,9 @@ class FrontPortForm(FrontPortFormMixin, ModularDeviceComponentForm):
|
||||
),
|
||||
)
|
||||
|
||||
port_mapping_model = PortMapping
|
||||
rear_port_model = RearPort
|
||||
|
||||
class Meta:
|
||||
model = FrontPort
|
||||
fields = [
|
||||
@@ -1630,13 +1611,12 @@ class FrontPortForm(FrontPortFormMixin, ModularDeviceComponentForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# Populate rear port choices
|
||||
if device_id := self.data.get('device') or self.initial.get('device'):
|
||||
device = Device.objects.get(pk=device_id)
|
||||
parent_filter = Q(device=device_id)
|
||||
else:
|
||||
return
|
||||
|
||||
# Populate rear port choices
|
||||
self.fields['rear_ports'].choices = self._get_rear_port_choices(device, self.instance)
|
||||
self.fields['rear_ports'].choices = self._get_rear_port_choices(parent_filter, self.instance)
|
||||
|
||||
# Set initial rear port mappings
|
||||
if self.instance.pk:
|
||||
@@ -1645,27 +1625,6 @@ class FrontPortForm(FrontPortFormMixin, ModularDeviceComponentForm):
|
||||
for mapping in PortMapping.objects.filter(front_port_id=self.instance.pk)
|
||||
]
|
||||
|
||||
def _get_rear_port_choices(self, device, front_port):
|
||||
"""
|
||||
Return a list of choices representing each available rear port & position pair on the device, excluding those
|
||||
assigned to the specified instance.
|
||||
"""
|
||||
occupied_rear_port_positions = [
|
||||
f'{mapping.rear_port_id}:{mapping.rear_port_position}'
|
||||
for mapping in device.port_mappings.exclude(front_port=front_port.pk)
|
||||
]
|
||||
|
||||
choices = []
|
||||
for rear_port in RearPort.objects.filter(device=device):
|
||||
for i in range(1, rear_port.positions + 1):
|
||||
pair_id = f'{rear_port.pk}:{i}'
|
||||
if pair_id not in occupied_rear_port_positions:
|
||||
pair_label = f'{rear_port.name}:{i}'
|
||||
choices.append(
|
||||
(pair_id, pair_label)
|
||||
)
|
||||
return choices
|
||||
|
||||
|
||||
class RearPortForm(ModularDeviceComponentForm):
|
||||
fieldsets = (
|
||||
|
||||
@@ -211,12 +211,16 @@ def sync_cached_scope_fields(instance, created, **kwargs):
|
||||
for model in (Prefix, Cluster, WirelessLAN):
|
||||
qs = model.objects.filter(**filters)
|
||||
|
||||
# Bulk update cached fields to avoid O(N) performance issues with large datasets.
|
||||
# This does not trigger post_save signals, avoiding spurious change log entries.
|
||||
objects_to_update = []
|
||||
for obj in qs:
|
||||
# Recompute cache using the same logic as save()
|
||||
obj.cache_related_objects()
|
||||
obj.save(update_fields=[
|
||||
'_location',
|
||||
'_site',
|
||||
'_site_group',
|
||||
'_region',
|
||||
])
|
||||
objects_to_update.append(obj)
|
||||
|
||||
if objects_to_update:
|
||||
model.objects.bulk_update(
|
||||
objects_to_update,
|
||||
['_location', '_site', '_site_group', '_region']
|
||||
)
|
||||
|
||||
@@ -31,7 +31,7 @@ class RackDimensionsPanel(panels.ObjectAttributesPanel):
|
||||
outer_width = attrs.NumericAttr('outer_width', unit_accessor='get_outer_unit_display')
|
||||
outer_height = attrs.NumericAttr('outer_height', unit_accessor='get_outer_unit_display')
|
||||
outer_depth = attrs.NumericAttr('outer_depth', unit_accessor='get_outer_unit_display')
|
||||
mounting_depth = attrs.TextAttr('mounting_depth', format_string='{}mm')
|
||||
mounting_depth = attrs.TextAttr('mounting_depth', format_string='{} mm')
|
||||
|
||||
|
||||
class RackNumberingPanel(panels.ObjectAttributesPanel):
|
||||
|
||||
@@ -1845,6 +1845,7 @@ class ModuleTypeBulkEditView(generic.BulkEditView):
|
||||
class ModuleTypeBulkRenameView(generic.BulkRenameView):
|
||||
queryset = ModuleType.objects.all()
|
||||
filterset = filtersets.ModuleTypeFilterSet
|
||||
field_name = 'model'
|
||||
|
||||
|
||||
@register_model_view(ModuleType, 'bulk_delete', path='delete', detail=False)
|
||||
|
||||
@@ -28,7 +28,7 @@ class ConfigContextProfileSerializer(PrimaryModelSerializer):
|
||||
)
|
||||
data_file = DataFileSerializer(
|
||||
nested=True,
|
||||
read_only=True
|
||||
required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@@ -143,7 +143,7 @@ class ConfigContextSerializer(OwnerMixin, ChangeLogMessageSerializer, ValidatedM
|
||||
)
|
||||
data_file = DataFileSerializer(
|
||||
nested=True,
|
||||
read_only=True
|
||||
required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import datetime
|
||||
import hashlib
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.urls import reverse
|
||||
@@ -7,7 +8,7 @@ from rest_framework import status
|
||||
|
||||
from core.choices import ManagedFileRootPathChoices
|
||||
from core.events import *
|
||||
from core.models import ObjectType
|
||||
from core.models import DataFile, DataSource, ObjectType
|
||||
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Rack, Location, RackRole, Site
|
||||
from extras.choices import *
|
||||
from extras.models import *
|
||||
@@ -731,6 +732,51 @@ class ConfigContextProfileTest(APIViewTestCases.APIViewTestCase):
|
||||
)
|
||||
ConfigContextProfile.objects.bulk_create(profiles)
|
||||
|
||||
def test_update_data_source_and_data_file(self):
|
||||
"""
|
||||
Regression test: Ensure data_source and data_file can be assigned via the API.
|
||||
|
||||
This specifically covers PATCHing a ConfigContext with integer IDs for both fields.
|
||||
"""
|
||||
self.add_permissions(
|
||||
'core.view_datafile',
|
||||
'core.view_datasource',
|
||||
'extras.view_configcontextprofile',
|
||||
'extras.change_configcontextprofile',
|
||||
)
|
||||
config_context_profile = ConfigContextProfile.objects.first()
|
||||
|
||||
# Create a data source and file
|
||||
datasource = DataSource.objects.create(
|
||||
name='Data Source 1',
|
||||
type='local',
|
||||
source_url='file:///tmp/netbox-datasource/',
|
||||
)
|
||||
# Generate a valid dummy YAML file
|
||||
file_data = b'profile: configcontext\n'
|
||||
datafile = DataFile.objects.create(
|
||||
source=datasource,
|
||||
path='dir1/file1.yml',
|
||||
last_updated=now(),
|
||||
size=len(file_data),
|
||||
hash=hashlib.sha256(file_data).hexdigest(),
|
||||
data=file_data,
|
||||
)
|
||||
|
||||
url = self._get_detail_url(config_context_profile)
|
||||
payload = {
|
||||
'data_source': datasource.pk,
|
||||
'data_file': datafile.pk,
|
||||
}
|
||||
response = self.client.patch(url, payload, format='json', **self.header)
|
||||
self.assertHttpStatus(response, status.HTTP_200_OK)
|
||||
|
||||
config_context_profile.refresh_from_db()
|
||||
self.assertEqual(config_context_profile.data_source_id, datasource.pk)
|
||||
self.assertEqual(config_context_profile.data_file_id, datafile.pk)
|
||||
self.assertEqual(response.data['data_source']['id'], datasource.pk)
|
||||
self.assertEqual(response.data['data_file']['id'], datafile.pk)
|
||||
|
||||
|
||||
class ConfigContextTest(APIViewTestCases.APIViewTestCase):
|
||||
model = ConfigContext
|
||||
@@ -812,6 +858,51 @@ class ConfigContextTest(APIViewTestCases.APIViewTestCase):
|
||||
rendered_context = device.get_config_context()
|
||||
self.assertEqual(rendered_context['bar'], 456)
|
||||
|
||||
def test_update_data_source_and_data_file(self):
|
||||
"""
|
||||
Regression test: Ensure data_source and data_file can be assigned via the API.
|
||||
|
||||
This specifically covers PATCHing a ConfigContext with integer IDs for both fields.
|
||||
"""
|
||||
self.add_permissions(
|
||||
'core.view_datafile',
|
||||
'core.view_datasource',
|
||||
'extras.view_configcontext',
|
||||
'extras.change_configcontext',
|
||||
)
|
||||
config_context = ConfigContext.objects.first()
|
||||
|
||||
# Create a data source and file
|
||||
datasource = DataSource.objects.create(
|
||||
name='Data Source 1',
|
||||
type='local',
|
||||
source_url='file:///tmp/netbox-datasource/',
|
||||
)
|
||||
# Generate a valid dummy YAML file
|
||||
file_data = b'context: config\n'
|
||||
datafile = DataFile.objects.create(
|
||||
source=datasource,
|
||||
path='dir1/file1.yml',
|
||||
last_updated=now(),
|
||||
size=len(file_data),
|
||||
hash=hashlib.sha256(file_data).hexdigest(),
|
||||
data=file_data,
|
||||
)
|
||||
|
||||
url = self._get_detail_url(config_context)
|
||||
payload = {
|
||||
'data_source': datasource.pk,
|
||||
'data_file': datafile.pk,
|
||||
}
|
||||
response = self.client.patch(url, payload, format='json', **self.header)
|
||||
self.assertHttpStatus(response, status.HTTP_200_OK)
|
||||
|
||||
config_context.refresh_from_db()
|
||||
self.assertEqual(config_context.data_source_id, datasource.pk)
|
||||
self.assertEqual(config_context.data_file_id, datafile.pk)
|
||||
self.assertEqual(response.data['data_source']['id'], datasource.pk)
|
||||
self.assertEqual(response.data['data_file']['id'], datafile.pk)
|
||||
|
||||
|
||||
class ConfigTemplateTest(APIViewTestCases.APIViewTestCase):
|
||||
model = ConfigTemplate
|
||||
|
||||
@@ -538,7 +538,7 @@ class VLANFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
|
||||
FieldSet('qinq_role', 'qinq_svlan_id', name=_('Q-in-Q/802.1ad')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
)
|
||||
selector_fields = ('filter_id', 'q', 'site_id')
|
||||
selector_fields = ('filter_id', 'q', 'group_id')
|
||||
region_id = DynamicModelMultipleChoiceField(
|
||||
queryset=Region.objects.all(),
|
||||
required=False,
|
||||
|
||||
@@ -372,8 +372,8 @@ class IPAddressForm(TenancyForm, PrimaryModelForm):
|
||||
'virtual_machine_id': instance.assigned_object.virtual_machine.pk,
|
||||
})
|
||||
|
||||
# Disable object assignment fields if the IP address is designated as primary
|
||||
if self.initial.get('primary_for_parent'):
|
||||
# Disable object assignment fields if the IP address is designated as primary or OOB
|
||||
if self.initial.get('primary_for_parent') or self.initial.get('oob_for_parent'):
|
||||
self.fields['interface'].disabled = True
|
||||
self.fields['vminterface'].disabled = True
|
||||
self.fields['fhrpgroup'].disabled = True
|
||||
|
||||
@@ -940,6 +940,13 @@ class IPAddress(ContactsMixin, PrimaryModel):
|
||||
_("Cannot reassign IP address while it is designated as the primary IP for the parent object")
|
||||
)
|
||||
|
||||
# can't use is_oob_ip as self.assigned_object might be changed
|
||||
if hasattr(original_parent, 'oob_ip') and original_parent.oob_ip_id == self.pk:
|
||||
if parent != original_parent:
|
||||
raise ValidationError(
|
||||
_("Cannot reassign IP address while it is designated as the OOB IP for the parent object")
|
||||
)
|
||||
|
||||
# Validate IP status selection
|
||||
if self.status == IPAddressStatusChoices.STATUS_SLAAC and self.family != 6:
|
||||
raise ValidationError({
|
||||
|
||||
@@ -3,7 +3,7 @@ from typing import TYPE_CHECKING
|
||||
|
||||
import strawberry_django
|
||||
from strawberry import ID
|
||||
from strawberry_django import FilterLookup
|
||||
from strawberry_django import ComparisonFilterLookup, FilterLookup
|
||||
|
||||
from core.graphql.filter_mixins import ChangeLoggingMixin
|
||||
from extras.graphql.filter_mixins import CustomFieldsFilterMixin, JournalEntriesFilterMixin, TagsFilterMixin
|
||||
@@ -23,7 +23,7 @@ __all__ = (
|
||||
|
||||
@dataclass
|
||||
class BaseModelFilter:
|
||||
id: FilterLookup[ID] | None = strawberry_django.filter_field()
|
||||
id: ComparisonFilterLookup[ID] | None = strawberry_django.filter_field()
|
||||
|
||||
|
||||
class ChangeLoggedModelFilter(ChangeLoggingMixin, BaseModelFilter):
|
||||
|
||||
@@ -164,7 +164,7 @@ class ObjectAttributesPanel(ObjectPanel, metaclass=ObjectAttributesPanelMeta):
|
||||
"""
|
||||
label = name[:1].upper() + name[1:]
|
||||
label = label.replace('_', ' ')
|
||||
return label
|
||||
return _(label)
|
||||
|
||||
def get_context(self, context):
|
||||
# Determine which attributes to display in the panel based on only/exclude args
|
||||
|
||||
2
netbox/project-static/dist/netbox.js
vendored
2
netbox/project-static/dist/netbox.js
vendored
File diff suppressed because one or more lines are too long
6
netbox/project-static/dist/netbox.js.map
vendored
6
netbox/project-static/dist/netbox.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -75,16 +75,10 @@ export class DynamicTomSelect extends TomSelect {
|
||||
load(value: string) {
|
||||
const self = this;
|
||||
|
||||
// Save current selection before clearing
|
||||
const currentValue = self.getValue();
|
||||
|
||||
// Automatically clear any cached options. (Only options included
|
||||
// in the API response should be present.)
|
||||
self.clearOptions();
|
||||
|
||||
// Clear user_options to prevent the pre-selected option from being treated specially
|
||||
(self as any).user_options = {};
|
||||
|
||||
// Populate the null option (if any) if not searching
|
||||
if (self.nullOption && !value) {
|
||||
self.addOption(self.nullOption);
|
||||
@@ -104,29 +98,16 @@ export class DynamicTomSelect extends TomSelect {
|
||||
.then(response => response.json())
|
||||
.then(apiData => {
|
||||
const results: Dict[] = apiData.results;
|
||||
|
||||
// Add options and manually set $order to ensure correct sorting
|
||||
results.forEach((result, index) => {
|
||||
const options: Dict[] = [];
|
||||
for (const result of results) {
|
||||
const option = self.getOptionFromData(result);
|
||||
self.addOption(option);
|
||||
// Set $order after addOption() to override any special handling of pre-selected items
|
||||
const key = option[self.settings.valueField as string] as string;
|
||||
if (self.options[key]) {
|
||||
(self.options[key] as any).$order = index;
|
||||
options.push(option);
|
||||
}
|
||||
});
|
||||
|
||||
self.loading--;
|
||||
if (self.loading === 0) {
|
||||
self.wrapper.classList.remove(self.settings.loadingClass as string);
|
||||
}
|
||||
|
||||
// Restore the current selection
|
||||
if (currentValue && !self.items.includes(currentValue as string)) {
|
||||
self.items.push(currentValue as string);
|
||||
}
|
||||
|
||||
self.refreshOptions(false);
|
||||
return options;
|
||||
})
|
||||
// Pass the options to the callback function
|
||||
.then(options => {
|
||||
self.loadCallback(options, []);
|
||||
})
|
||||
.catch(() => {
|
||||
self.loadCallback([], []);
|
||||
|
||||
@@ -49,9 +49,6 @@ export function initDynamicSelects(): void {
|
||||
labelField: LABEL_FIELD,
|
||||
maxOptions: MAX_OPTIONS,
|
||||
|
||||
// Preserve API response order
|
||||
sortField: '$order',
|
||||
|
||||
// Disable local search (search is performed on the backend)
|
||||
searchField: [],
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-13 05:05+0000\n"
|
||||
"POT-Creation-Date: 2026-01-17 05:02+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"
|
||||
@@ -806,7 +806,7 @@ msgstr ""
|
||||
#: 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:1917
|
||||
#: netbox/dcim/forms/model_forms.py:863 netbox/dcim/forms/model_forms.py:1877
|
||||
#: 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
|
||||
@@ -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:1235
|
||||
#: netbox/dcim/forms/model_forms.py:1737 netbox/dcim/forms/object_import.py:182
|
||||
#: 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/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:1309
|
||||
#: netbox/dcim/forms/model_forms.py:1578 netbox/dcim/forms/model_forms.py:1778
|
||||
#: netbox/dcim/forms/model_forms.py:1813 netbox/dcim/forms/model_forms.py:1938
|
||||
#: 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/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
|
||||
@@ -1852,8 +1852,8 @@ msgstr ""
|
||||
#: 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:1376
|
||||
#: netbox/dcim/forms/model_forms.py:1889 netbox/dcim/forms/model_forms.py:1962
|
||||
#: 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/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
|
||||
@@ -2435,7 +2435,7 @@ msgstr ""
|
||||
msgid "Change logging is not supported for this object type ({type})."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/config.py:21 netbox/core/models/data.py:282
|
||||
#: netbox/core/models/config.py:21 netbox/core/models/data.py:284
|
||||
#: netbox/core/models/files.py:29 netbox/core/models/jobs.py:60
|
||||
#: netbox/extras/models/models.py:847 netbox/extras/models/notifications.py:39
|
||||
#: netbox/extras/models/notifications.py:195
|
||||
@@ -2541,58 +2541,63 @@ msgstr ""
|
||||
msgid "Unknown backend type: {type}"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/data.py:180
|
||||
#: netbox/core/models/data.py:131
|
||||
#, python-brace-format
|
||||
msgid "URLs for local sources must start with {scheme} (or specify no scheme)"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/data.py:182
|
||||
msgid "Cannot initiate sync; syncing already in progress."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/data.py:193
|
||||
#: netbox/core/models/data.py:195
|
||||
msgid ""
|
||||
"There was an error initializing the backend. A dependency needs to be "
|
||||
"installed: "
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/data.py:286 netbox/core/models/files.py:33
|
||||
#: netbox/core/models/data.py:288 netbox/core/models/files.py:33
|
||||
#: netbox/netbox/models/features.py:67
|
||||
msgid "last updated"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/data.py:296 netbox/dcim/models/cables.py:622
|
||||
#: netbox/core/models/data.py:298 netbox/dcim/models/cables.py:622
|
||||
msgid "path"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/data.py:299
|
||||
#: netbox/core/models/data.py:301
|
||||
msgid "File path relative to the data source's root"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/data.py:303 netbox/ipam/models/ip.py:507
|
||||
#: netbox/core/models/data.py:305 netbox/ipam/models/ip.py:507
|
||||
msgid "size"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/data.py:306
|
||||
#: netbox/core/models/data.py:308
|
||||
msgid "hash"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/data.py:310
|
||||
#: netbox/core/models/data.py:312
|
||||
msgid "Length must be 64 hexadecimal characters."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/data.py:312
|
||||
#: netbox/core/models/data.py:314
|
||||
msgid "SHA256 hash of the file data"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/data.py:326
|
||||
#: netbox/core/models/data.py:328
|
||||
msgid "data file"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/data.py:327
|
||||
#: netbox/core/models/data.py:329
|
||||
msgid "data files"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/data.py:400
|
||||
#: netbox/core/models/data.py:402
|
||||
msgid "auto sync record"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/data.py:401
|
||||
#: netbox/core/models/data.py:403
|
||||
msgid "auto sync records"
|
||||
msgstr ""
|
||||
|
||||
@@ -3079,8 +3084,8 @@ msgstr ""
|
||||
#: 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:1227
|
||||
#: netbox/dcim/forms/model_forms.py:1729 netbox/dcim/forms/object_import.py:177
|
||||
#: 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/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
|
||||
@@ -3212,7 +3217,7 @@ 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:1590 netbox/netbox/navigation/menu.py:147
|
||||
#: netbox/dcim/forms/model_forms.py:1569 netbox/netbox/navigation/menu.py:147
|
||||
#: netbox/netbox/navigation/menu.py:151
|
||||
#: netbox/templates/dcim/interface.html:280
|
||||
msgid "Wireless"
|
||||
@@ -3830,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:1935 netbox/dcim/models/devices.py:1307
|
||||
#: netbox/dcim/forms/model_forms.py:1895 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
|
||||
@@ -3996,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:1556
|
||||
#: netbox/dcim/forms/model_forms.py:1535
|
||||
#: 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
|
||||
@@ -4055,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:1573
|
||||
#: netbox/dcim/forms/model_forms.py:1552
|
||||
#: 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
|
||||
@@ -4109,14 +4114,14 @@ msgstr ""
|
||||
msgid "Primary MAC address (ID)"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/filtersets.py:2057 netbox/dcim/forms/model_forms.py:1560
|
||||
#: netbox/dcim/filtersets.py:2057 netbox/dcim/forms/model_forms.py:1539
|
||||
#: 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:1915
|
||||
#: netbox/dcim/forms/filtersets.py:1569 netbox/dcim/forms/model_forms.py:1875
|
||||
#: netbox/templates/dcim/virtualdevicecontext.html:15
|
||||
msgid "Virtual Device Context"
|
||||
msgstr ""
|
||||
@@ -4238,7 +4243,7 @@ msgstr ""
|
||||
#: 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:1240 netbox/dcim/forms/model_forms.py:1742
|
||||
#: netbox/dcim/forms/model_forms.py:1219 netbox/dcim/forms/model_forms.py:1702
|
||||
#: 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
|
||||
@@ -4416,7 +4421,7 @@ msgstr ""
|
||||
#: 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:1810
|
||||
#: netbox/dcim/forms/model_forms.py:1770
|
||||
#: netbox/templates/dcim/device_edit.html:22
|
||||
msgid "Hardware"
|
||||
msgstr ""
|
||||
@@ -4442,8 +4447,8 @@ 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:1181
|
||||
#: netbox/dcim/forms/model_forms.py:1199 netbox/dcim/forms/object_create.py:117
|
||||
#: 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/tables/devicetypes.py:83 netbox/templates/dcim/devicebay.html:52
|
||||
#: netbox/templates/dcim/module.html:61
|
||||
msgid "Device Type"
|
||||
@@ -4472,7 +4477,7 @@ msgstr ""
|
||||
#: 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:1182 netbox/dcim/forms/model_forms.py:1200
|
||||
#: netbox/dcim/forms/model_forms.py:1161 netbox/dcim/forms/model_forms.py:1179
|
||||
#: 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
|
||||
@@ -4656,8 +4661,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:1446
|
||||
#: netbox/dcim/forms/model_forms.py:1794 netbox/dcim/forms/object_import.py:56
|
||||
#: 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
|
||||
msgid "Power port"
|
||||
msgstr ""
|
||||
|
||||
@@ -4692,7 +4697,7 @@ msgid "Wireless role"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/model_forms.py:766
|
||||
#: netbox/dcim/forms/model_forms.py:1391 netbox/dcim/tables/devices.py:328
|
||||
#: netbox/dcim/forms/model_forms.py:1370 netbox/dcim/tables/devices.py:328
|
||||
#: netbox/templates/dcim/consoleport.html:24
|
||||
#: netbox/templates/dcim/consoleserverport.html:24
|
||||
#: netbox/templates/dcim/frontport.html:24
|
||||
@@ -4710,7 +4715,7 @@ msgstr ""
|
||||
msgid "LAG"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/model_forms.py:1473
|
||||
#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/model_forms.py:1452
|
||||
msgid "Virtual device contexts"
|
||||
msgstr ""
|
||||
|
||||
@@ -4739,7 +4744,7 @@ msgid "Mode"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_edit.py:1458 netbox/dcim/forms/bulk_import.py:993
|
||||
#: netbox/dcim/forms/model_forms.py:1522 netbox/ipam/forms/bulk_import.py:173
|
||||
#: netbox/dcim/forms/model_forms.py:1501 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
|
||||
@@ -4748,7 +4753,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:1528 netbox/dcim/tables/devices.py:605
|
||||
#: netbox/dcim/forms/model_forms.py:1507 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
|
||||
@@ -4756,7 +4761,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:1537 netbox/dcim/tables/devices.py:611
|
||||
#: netbox/dcim/forms/model_forms.py:1516 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
|
||||
@@ -4772,18 +4777,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:1546
|
||||
#: netbox/dcim/forms/model_forms.py:1525
|
||||
#: 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:1509
|
||||
#: netbox/dcim/forms/bulk_edit.py:1514 netbox/dcim/forms/model_forms.py:1488
|
||||
#: netbox/wireless/forms/filtersets.py:26
|
||||
msgid "Wireless LAN group"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_edit.py:1519 netbox/dcim/forms/model_forms.py:1514
|
||||
#: netbox/dcim/forms/bulk_edit.py:1519 netbox/dcim/forms/model_forms.py:1493
|
||||
#: netbox/dcim/tables/devices.py:653 netbox/netbox/navigation/menu.py:153
|
||||
#: netbox/templates/dcim/interface.html:350
|
||||
#: netbox/wireless/tables/wirelesslan.py:20
|
||||
@@ -4791,7 +4796,7 @@ msgid "Wireless LANs"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_edit.py:1528 netbox/dcim/forms/filtersets.py:1550
|
||||
#: netbox/dcim/forms/model_forms.py:1580 netbox/ipam/forms/bulk_edit.py:224
|
||||
#: netbox/dcim/forms/model_forms.py:1559 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
|
||||
@@ -4803,18 +4808,18 @@ msgid "Addressing"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_edit.py:1529 netbox/dcim/forms/filtersets.py:808
|
||||
#: netbox/dcim/forms/model_forms.py:1581
|
||||
#: netbox/dcim/forms/model_forms.py:1560
|
||||
#: 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:1583
|
||||
#: netbox/dcim/forms/model_forms.py:1562
|
||||
msgid "PoE"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_edit.py:1531 netbox/dcim/forms/model_forms.py:1582
|
||||
#: netbox/dcim/forms/bulk_edit.py:1531 netbox/dcim/forms/model_forms.py:1561
|
||||
#: netbox/templates/dcim/interface.html:105
|
||||
#: netbox/virtualization/forms/bulk_edit.py:237
|
||||
#: netbox/virtualization/forms/model_forms.py:371
|
||||
@@ -4822,7 +4827,7 @@ msgid "Related Interfaces"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_edit.py:1533 netbox/dcim/forms/filtersets.py:1552
|
||||
#: netbox/dcim/forms/model_forms.py:1586
|
||||
#: netbox/dcim/forms/model_forms.py:1565
|
||||
#: netbox/virtualization/forms/bulk_edit.py:240
|
||||
#: netbox/virtualization/forms/filtersets.py:215
|
||||
#: netbox/virtualization/forms/model_forms.py:374
|
||||
@@ -5101,13 +5106,13 @@ msgstr ""
|
||||
msgid "Electrical phase (for three-phase circuits)"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:939 netbox/dcim/forms/model_forms.py:1484
|
||||
#: netbox/dcim/forms/bulk_import.py:939 netbox/dcim/forms/model_forms.py:1463
|
||||
#: 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:1492
|
||||
#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/model_forms.py:1471
|
||||
#: netbox/virtualization/forms/bulk_import.py:176
|
||||
#: netbox/virtualization/forms/model_forms.py:318
|
||||
msgid "Bridged interface"
|
||||
@@ -5390,7 +5395,7 @@ msgstr ""
|
||||
msgid "Single or three-phase"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1729 netbox/dcim/forms/model_forms.py:1895
|
||||
#: netbox/dcim/forms/bulk_import.py:1729 netbox/dcim/forms/model_forms.py:1855
|
||||
#: netbox/dcim/ui/panels.py:109
|
||||
#: netbox/templates/dcim/virtualdevicecontext.html:30
|
||||
#: netbox/templates/virtualization/virtualmachine.html:56
|
||||
@@ -5401,7 +5406,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:1904
|
||||
#: netbox/dcim/forms/bulk_import.py:1736 netbox/dcim/forms/model_forms.py:1864
|
||||
#: netbox/dcim/ui/panels.py:114
|
||||
#: netbox/templates/dcim/virtualdevicecontext.html:41
|
||||
#: netbox/templates/virtualization/virtualmachine.html:72
|
||||
@@ -5604,7 +5609,7 @@ msgstr ""
|
||||
msgid "Mgmt only"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/filtersets.py:1613 netbox/dcim/forms/model_forms.py:1568
|
||||
#: netbox/dcim/forms/filtersets.py:1613 netbox/dcim/forms/model_forms.py:1547
|
||||
#: netbox/dcim/models/device_components.py:791
|
||||
#: netbox/templates/dcim/interface.html:155
|
||||
msgid "WWN"
|
||||
@@ -5705,7 +5710,7 @@ msgstr ""
|
||||
msgid "Rear ports"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/mixins.py:158
|
||||
#: netbox/dcim/forms/mixins.py:155
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"The total number of front port positions ({frontport_count}) must match the "
|
||||
@@ -5777,35 +5782,35 @@ msgid ""
|
||||
"replaced with the position value when creating a new module."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1252
|
||||
#: netbox/dcim/forms/model_forms.py:1231
|
||||
msgid "Console port template"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1260
|
||||
#: netbox/dcim/forms/model_forms.py:1239
|
||||
msgid "Console server port template"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1268
|
||||
#: netbox/dcim/forms/model_forms.py:1247
|
||||
msgid "Front port template"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1276
|
||||
#: netbox/dcim/forms/model_forms.py:1255
|
||||
msgid "Interface template"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1284
|
||||
#: netbox/dcim/forms/model_forms.py:1263
|
||||
msgid "Power outlet template"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1292
|
||||
#: netbox/dcim/forms/model_forms.py:1271
|
||||
msgid "Power port template"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1300
|
||||
#: netbox/dcim/forms/model_forms.py:1279
|
||||
msgid "Rear port template"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1310 netbox/dcim/forms/model_forms.py:1814
|
||||
#: netbox/dcim/forms/model_forms.py:1289 netbox/dcim/forms/model_forms.py:1774
|
||||
#: netbox/dcim/tables/connections.py:27
|
||||
#: netbox/templates/dcim/consoleport.html:17
|
||||
#: netbox/templates/dcim/consoleserverport.html:73
|
||||
@@ -5813,14 +5818,14 @@ msgstr ""
|
||||
msgid "Console Port"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1311 netbox/dcim/forms/model_forms.py:1815
|
||||
#: netbox/dcim/forms/model_forms.py:1290 netbox/dcim/forms/model_forms.py:1775
|
||||
#: 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:1312 netbox/dcim/forms/model_forms.py:1816
|
||||
#: netbox/dcim/forms/model_forms.py:1291 netbox/dcim/forms/model_forms.py:1776
|
||||
#: netbox/templates/circuits/inc/circuit_termination_fields.html:53
|
||||
#: netbox/templates/dcim/consoleport.html:76
|
||||
#: netbox/templates/dcim/consoleserverport.html:76
|
||||
@@ -5832,7 +5837,7 @@ msgstr ""
|
||||
msgid "Front Port"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1313 netbox/dcim/forms/model_forms.py:1817
|
||||
#: netbox/dcim/forms/model_forms.py:1292 netbox/dcim/forms/model_forms.py:1777
|
||||
#: netbox/templates/circuits/inc/circuit_termination_fields.html:54
|
||||
#: netbox/templates/dcim/consoleport.html:79
|
||||
#: netbox/templates/dcim/consoleserverport.html:79
|
||||
@@ -5844,80 +5849,80 @@ msgstr ""
|
||||
msgid "Rear Port"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1314 netbox/dcim/forms/model_forms.py:1818
|
||||
#: netbox/dcim/forms/model_forms.py:1293 netbox/dcim/forms/model_forms.py:1778
|
||||
#: 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:1315 netbox/dcim/forms/model_forms.py:1819
|
||||
#: netbox/dcim/forms/model_forms.py:1294 netbox/dcim/forms/model_forms.py:1779
|
||||
#: netbox/templates/dcim/poweroutlet.html:17
|
||||
#: netbox/templates/dcim/powerport.html:77
|
||||
msgid "Power Outlet"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1317 netbox/dcim/forms/model_forms.py:1821
|
||||
#: netbox/dcim/forms/model_forms.py:1296 netbox/dcim/forms/model_forms.py:1781
|
||||
msgid "Component Assignment"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1363 netbox/dcim/forms/model_forms.py:1868
|
||||
#: netbox/dcim/forms/model_forms.py:1342 netbox/dcim/forms/model_forms.py:1828
|
||||
msgid "An InventoryItem can only be assigned to a single component."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1500
|
||||
#: netbox/dcim/forms/model_forms.py:1479
|
||||
msgid "LAG interface"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1523
|
||||
#: netbox/dcim/forms/model_forms.py:1502
|
||||
msgid "Filter VLANs available for assignment by group."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1711
|
||||
#: netbox/dcim/forms/model_forms.py:1671
|
||||
msgid "Child Device"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1712
|
||||
#: netbox/dcim/forms/model_forms.py:1672
|
||||
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:1754
|
||||
#: netbox/dcim/forms/model_forms.py:1714
|
||||
msgid "Console port"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1762
|
||||
#: netbox/dcim/forms/model_forms.py:1722
|
||||
msgid "Console server port"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1770 netbox/dcim/forms/object_import.py:140
|
||||
#: netbox/dcim/forms/model_forms.py:1730 netbox/dcim/forms/object_import.py:140
|
||||
msgid "Front port"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1786
|
||||
#: netbox/dcim/forms/model_forms.py:1746
|
||||
msgid "Power outlet"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1802 netbox/dcim/forms/object_import.py:145
|
||||
#: netbox/dcim/forms/model_forms.py:1762 netbox/dcim/forms/object_import.py:145
|
||||
msgid "Rear port"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1808
|
||||
#: netbox/dcim/forms/model_forms.py:1768
|
||||
#: netbox/templates/dcim/inventoryitem.html:17
|
||||
msgid "Inventory Item"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1877
|
||||
#: netbox/dcim/forms/model_forms.py:1837
|
||||
#: netbox/templates/dcim/inventoryitemrole.html:15
|
||||
msgid "Inventory Item Role"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1947
|
||||
#: netbox/dcim/forms/model_forms.py:1907
|
||||
msgid "VM Interface"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:1963 netbox/ipam/forms/filtersets.py:638
|
||||
#: netbox/dcim/forms/model_forms.py:1923 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
|
||||
@@ -5934,7 +5939,7 @@ msgstr ""
|
||||
msgid "Virtual Machine"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/model_forms.py:2002
|
||||
#: netbox/dcim/forms/model_forms.py:1962
|
||||
msgid "A MAC address can only be assigned to a single object."
|
||||
msgstr ""
|
||||
|
||||
@@ -7674,7 +7679,7 @@ msgstr ""
|
||||
|
||||
#: netbox/dcim/tables/devices.py:252 netbox/dcim/tables/devices.py:1125
|
||||
#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1412
|
||||
#: netbox/dcim/views.py:1749 netbox/dcim/views.py:2577
|
||||
#: netbox/dcim/views.py:1749 netbox/dcim/views.py:2578
|
||||
#: netbox/netbox/navigation/menu.py:95 netbox/netbox/navigation/menu.py:259
|
||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:38
|
||||
#: netbox/templates/dcim/device/base.html:37
|
||||
@@ -7721,7 +7726,7 @@ msgstr ""
|
||||
|
||||
#: netbox/dcim/tables/devices.py:333 netbox/dcim/tables/devicetypes.py:52
|
||||
#: netbox/dcim/tables/devicetypes.py:146 netbox/dcim/views.py:1487
|
||||
#: netbox/dcim/views.py:2663 netbox/netbox/navigation/menu.py:104
|
||||
#: netbox/dcim/views.py:2664 netbox/netbox/navigation/menu.py:104
|
||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:66
|
||||
#: netbox/templates/dcim/device/base.html:52
|
||||
#: netbox/templates/dcim/devicetype/base.html:49
|
||||
@@ -7855,7 +7860,7 @@ msgid "Device Count"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:1352
|
||||
#: netbox/dcim/views.py:1689 netbox/dcim/views.py:2512
|
||||
#: netbox/dcim/views.py:1689 netbox/dcim/views.py:2513
|
||||
#: netbox/netbox/navigation/menu.py:98
|
||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:10
|
||||
#: netbox/templates/dcim/device/base.html:25
|
||||
@@ -7866,7 +7871,7 @@ msgid "Console Ports"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1367
|
||||
#: netbox/dcim/views.py:1704 netbox/dcim/views.py:2528
|
||||
#: netbox/dcim/views.py:1704 netbox/dcim/views.py:2529
|
||||
#: netbox/netbox/navigation/menu.py:99
|
||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:17
|
||||
#: netbox/templates/dcim/device/base.html:28
|
||||
@@ -7877,7 +7882,7 @@ msgid "Console Server Ports"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1382
|
||||
#: netbox/dcim/views.py:1719 netbox/dcim/views.py:2544
|
||||
#: netbox/dcim/views.py:1719 netbox/dcim/views.py:2545
|
||||
#: netbox/netbox/navigation/menu.py:100
|
||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:24
|
||||
#: netbox/templates/dcim/device/base.html:31
|
||||
@@ -7888,7 +7893,7 @@ msgid "Power Ports"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1397
|
||||
#: netbox/dcim/views.py:1734 netbox/dcim/views.py:2560
|
||||
#: netbox/dcim/views.py:1734 netbox/dcim/views.py:2561
|
||||
#: netbox/netbox/navigation/menu.py:101
|
||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:31
|
||||
#: netbox/templates/dcim/device/base.html:34
|
||||
@@ -7899,7 +7904,7 @@ msgid "Power Outlets"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1427
|
||||
#: netbox/dcim/views.py:1764 netbox/dcim/views.py:2599
|
||||
#: netbox/dcim/views.py:1764 netbox/dcim/views.py:2600
|
||||
#: netbox/netbox/navigation/menu.py:96
|
||||
#: netbox/templates/dcim/device/base.html:40
|
||||
#: netbox/templates/dcim/devicetype/base.html:37
|
||||
@@ -7909,7 +7914,7 @@ msgid "Front Ports"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1442
|
||||
#: netbox/dcim/views.py:1779 netbox/dcim/views.py:2615
|
||||
#: netbox/dcim/views.py:1779 netbox/dcim/views.py:2616
|
||||
#: netbox/netbox/navigation/menu.py:97
|
||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:45
|
||||
#: netbox/templates/dcim/device/base.html:43
|
||||
@@ -7920,7 +7925,7 @@ msgid "Rear Ports"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1472
|
||||
#: netbox/dcim/views.py:2647 netbox/netbox/navigation/menu.py:103
|
||||
#: netbox/dcim/views.py:2648 netbox/netbox/navigation/menu.py:103
|
||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:52
|
||||
#: netbox/templates/dcim/device/base.html:49
|
||||
#: netbox/templates/dcim/devicetype/base.html:46
|
||||
@@ -7928,7 +7933,7 @@ msgid "Device Bays"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1457
|
||||
#: netbox/dcim/views.py:1794 netbox/dcim/views.py:2631
|
||||
#: netbox/dcim/views.py:1794 netbox/dcim/views.py:2632
|
||||
#: netbox/netbox/navigation/menu.py:102
|
||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:59
|
||||
#: netbox/templates/dcim/device/base.html:46
|
||||
@@ -8067,13 +8072,13 @@ msgstr ""
|
||||
msgid "Reservations"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/views.py:2458 netbox/netbox/navigation/menu.py:213
|
||||
#: netbox/dcim/views.py:2459 netbox/netbox/navigation/menu.py:213
|
||||
#: netbox/templates/ipam/ipaddress.html:118
|
||||
#: netbox/templates/virtualization/virtualmachine.html:160
|
||||
msgid "Application Services"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/views.py:2676 netbox/extras/forms/filtersets.py:427
|
||||
#: netbox/dcim/views.py:2677 netbox/extras/forms/filtersets.py:427
|
||||
#: netbox/extras/forms/model_forms.py:691
|
||||
#: netbox/templates/extras/configcontext.html:10
|
||||
#: netbox/virtualization/forms/model_forms.py:225
|
||||
@@ -8081,41 +8086,41 @@ msgstr ""
|
||||
msgid "Config Context"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/views.py:2687 netbox/virtualization/views.py:410
|
||||
#: netbox/dcim/views.py:2688 netbox/virtualization/views.py:410
|
||||
msgid "Render Config"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/views.py:2700 netbox/extras/tables/tables.py:713
|
||||
#: netbox/dcim/views.py:2701 netbox/extras/tables/tables.py:713
|
||||
#: netbox/netbox/navigation/menu.py:256 netbox/netbox/navigation/menu.py:258
|
||||
#: netbox/virtualization/views.py:224
|
||||
msgid "Virtual Machines"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/views.py:3509
|
||||
#: netbox/dcim/views.py:3510
|
||||
#, python-brace-format
|
||||
msgid "Installed device {device} in bay {device_bay}."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/views.py:3550
|
||||
#: netbox/dcim/views.py:3551
|
||||
#, python-brace-format
|
||||
msgid "Removed device {device} from bay {device_bay}."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/views.py:3663 netbox/ipam/tables/ip.py:178
|
||||
#: netbox/dcim/views.py:3664 netbox/ipam/tables/ip.py:178
|
||||
msgid "Children"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/views.py:4136
|
||||
#: netbox/dcim/views.py:4137
|
||||
#, python-brace-format
|
||||
msgid "Added member <a href=\"{url}\">{device}</a>"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/views.py:4181
|
||||
#: netbox/dcim/views.py:4182
|
||||
#, python-brace-format
|
||||
msgid "Unable to remove master device {device} from the virtual chassis."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/views.py:4192
|
||||
#: netbox/dcim/views.py:4193
|
||||
#, python-brace-format
|
||||
msgid "Removed {device} from virtual chassis {chassis}"
|
||||
msgstr ""
|
||||
@@ -11240,7 +11245,13 @@ msgid ""
|
||||
"parent object"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/ipam/models/ip.py:946
|
||||
#: netbox/ipam/models/ip.py:947
|
||||
msgid ""
|
||||
"Cannot reassign IP address while it is designated as the OOB IP for the "
|
||||
"parent object"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/ipam/models/ip.py:953
|
||||
msgid "Only IPv6 addresses can be assigned SLAAC status"
|
||||
msgstr ""
|
||||
|
||||
@@ -12489,8 +12500,8 @@ msgstr ""
|
||||
msgid "Delete Selected"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/plugins/navigation.py:55
|
||||
#: netbox/netbox/plugins/navigation.py:88
|
||||
#: netbox/netbox/plugins/navigation.py:53
|
||||
#: netbox/netbox/plugins/navigation.py:89
|
||||
msgid "Permissions must be passed as a tuple or list."
|
||||
msgstr ""
|
||||
|
||||
@@ -12498,7 +12509,7 @@ msgstr ""
|
||||
msgid "Buttons must be passed as a tuple or list."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/plugins/navigation.py:92
|
||||
#: netbox/netbox/plugins/navigation.py:95
|
||||
msgid "Button color must be a choice within ButtonColorChoices."
|
||||
msgstr ""
|
||||
|
||||
@@ -16576,7 +16587,7 @@ msgstr ""
|
||||
msgid "Missing required value for static query param: '{static_params}'"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/utilities/forms/widgets/modifiers.py:111
|
||||
#: netbox/utilities/forms/widgets/modifiers.py:141
|
||||
msgid "(automatically set)"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from utilities.forms.widgets.apiselect import APISelect, APISelectMultiple
|
||||
|
||||
__all__ = (
|
||||
'FilterModifierWidget',
|
||||
'MODIFIER_EMPTY_FALSE',
|
||||
@@ -94,9 +96,37 @@ class FilterModifierWidget(forms.Widget):
|
||||
# to the original widget before rendering
|
||||
self.original_widget.attrs.update(self.attrs)
|
||||
|
||||
# For APISelect/APISelectMultiple widgets, temporarily clear choices to prevent queryset evaluation
|
||||
original_choices = None
|
||||
if isinstance(self.original_widget, (APISelect, APISelectMultiple)):
|
||||
original_choices = self.original_widget.choices
|
||||
|
||||
# Only keep selected choices to preserve current selection in HTML
|
||||
if value:
|
||||
values = value if isinstance(value, (list, tuple)) else [value]
|
||||
|
||||
if hasattr(original_choices, 'queryset'):
|
||||
queryset = original_choices.queryset
|
||||
selected_objects = queryset.filter(pk__in=values)
|
||||
# Build minimal choice list with just the selected values
|
||||
self.original_widget.choices = [
|
||||
(obj.pk, str(obj)) for obj in selected_objects
|
||||
]
|
||||
else:
|
||||
self.original_widget.choices = [
|
||||
choice for choice in original_choices if choice[0] in values
|
||||
]
|
||||
else:
|
||||
# No selection - render empty select element
|
||||
self.original_widget.choices = []
|
||||
|
||||
# Get context from the original widget
|
||||
original_context = self.original_widget.get_context(name, value, attrs)
|
||||
|
||||
# Restore original choices if we modified them
|
||||
if original_choices is not None:
|
||||
self.original_widget.choices = original_choices
|
||||
|
||||
# Build our wrapper context
|
||||
context = super().get_context(name, value, attrs)
|
||||
context['widget']['original_widget'] = original_context['widget']
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
# TODO: Remove this file in NetBox v4.3
|
||||
# This script has been maintained to ease transition to the pre-commit tool.
|
||||
|
||||
exec 1>&2
|
||||
|
||||
EXIT=0
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[0;33m'
|
||||
NOCOLOR='\033[0m'
|
||||
|
||||
printf "${YELLOW}The pre-commit hook script is obsolete. Please use pre-commit instead:${NOCOLOR}\n"
|
||||
printf " pip install pre-commit\n"
|
||||
printf " pre-commit install${NOCOLOR}\n"
|
||||
|
||||
exit 1
|
||||
Reference in New Issue
Block a user