mirror of
https://github.com/netbox-community/netbox.git
synced 2026-01-19 01:58:43 -06:00
Compare commits
6 Commits
21039-avif
...
20911-drop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a1282e326 | ||
|
|
cb13eb277f | ||
|
|
24642be351 | ||
|
|
89af9efd85 | ||
|
|
99d678502f | ||
|
|
e6300ee06d |
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
@@ -30,13 +30,13 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v4
|
uses: github/codeql-action/init@v3
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
build-mode: ${{ matrix.build-mode }}
|
build-mode: ${{ matrix.build-mode }}
|
||||||
config-file: .github/codeql/codeql-config.yml
|
config-file: .github/codeql/codeql-config.yml
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v4
|
uses: github/codeql-action/analyze@v3
|
||||||
with:
|
with:
|
||||||
category: "/language:${{matrix.language}}"
|
category: "/language:${{matrix.language}}"
|
||||||
|
|||||||
@@ -44,4 +44,3 @@ class DataFileSerializer(NetBoxModelSerializer):
|
|||||||
'id', 'url', 'display_url', 'display', 'source', 'path', 'last_updated', 'size', 'hash',
|
'id', 'url', 'display_url', 'display', 'source', 'path', 'last_updated', 'size', 'hash',
|
||||||
]
|
]
|
||||||
brief_fields = ('id', 'url', 'display', 'path')
|
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.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from netbox.constants import CENSOR_TOKEN, CENSOR_TOKEN_CHANGED
|
from netbox.constants import CENSOR_TOKEN, CENSOR_TOKEN_CHANGED
|
||||||
from netbox.models import PrimaryModel
|
from netbox.models import PrimaryModel
|
||||||
@@ -128,9 +128,7 @@ class DataSource(JobsMixin, PrimaryModel):
|
|||||||
# Ensure URL scheme matches selected type
|
# Ensure URL scheme matches selected type
|
||||||
if self.backend_class.is_local and self.url_scheme not in ('file', ''):
|
if self.backend_class.is_local and self.url_scheme not in ('file', ''):
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
'source_url': _("URLs for local sources must start with {scheme} (or specify no scheme)").format(
|
'source_url': "URLs for local sources must start with file:// (or specify no scheme)"
|
||||||
scheme='file://'
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
|
|||||||
@@ -140,6 +140,9 @@ class FrontPortFormMixin(forms.Form):
|
|||||||
widget=forms.SelectMultiple(attrs={'size': 8})
|
widget=forms.SelectMultiple(attrs={'size': 8})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
port_mapping_model = PortMapping
|
||||||
|
parent_field = 'device'
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
super().clean()
|
super().clean()
|
||||||
|
|
||||||
@@ -200,22 +203,3 @@ class FrontPortFormMixin(forms.Form):
|
|||||||
using=connection,
|
using=connection,
|
||||||
update_fields=None
|
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,9 +733,10 @@ class ModuleForm(ModuleCommonForm, PrimaryModelForm):
|
|||||||
)
|
)
|
||||||
module_bay = DynamicModelChoiceField(
|
module_bay = DynamicModelChoiceField(
|
||||||
label=_('Module bay'),
|
label=_('Module bay'),
|
||||||
queryset=ModuleBay.objects.all(),
|
queryset=ModuleBay.objects.order_by('name'),
|
||||||
query_params={
|
query_params={
|
||||||
'device_id': '$device'
|
'device_id': '$device',
|
||||||
|
'ordering': 'name',
|
||||||
},
|
},
|
||||||
context={
|
context={
|
||||||
'disabled': 'installed_module',
|
'disabled': 'installed_module',
|
||||||
@@ -1124,8 +1125,9 @@ class FrontPortTemplateForm(FrontPortFormMixin, ModularComponentTemplateForm):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Override FrontPortFormMixin attrs
|
||||||
port_mapping_model = PortTemplateMapping
|
port_mapping_model = PortTemplateMapping
|
||||||
rear_port_model = RearPortTemplate
|
parent_field = 'device_type'
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = FrontPortTemplate
|
model = FrontPortTemplate
|
||||||
@@ -1136,14 +1138,13 @@ class FrontPortTemplateForm(FrontPortFormMixin, ModularComponentTemplateForm):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*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'):
|
if device_type_id := self.data.get('device_type') or self.initial.get('device_type'):
|
||||||
parent_filter = Q(device_type=device_type_id)
|
device_type = DeviceType.objects.get(pk=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:
|
else:
|
||||||
return
|
return
|
||||||
self.fields['rear_ports'].choices = self._get_rear_port_choices(parent_filter, self.instance)
|
|
||||||
|
# Populate rear port choices
|
||||||
|
self.fields['rear_ports'].choices = self._get_rear_port_choices(device_type, self.instance)
|
||||||
|
|
||||||
# Set initial rear port mappings
|
# Set initial rear port mappings
|
||||||
if self.instance.pk:
|
if self.instance.pk:
|
||||||
@@ -1152,6 +1153,27 @@ class FrontPortTemplateForm(FrontPortFormMixin, ModularComponentTemplateForm):
|
|||||||
for mapping in PortTemplateMapping.objects.filter(front_port_id=self.instance.pk)
|
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):
|
class RearPortTemplateForm(ModularComponentTemplateForm):
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
@@ -1598,9 +1620,6 @@ class FrontPortForm(FrontPortFormMixin, ModularDeviceComponentForm):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
port_mapping_model = PortMapping
|
|
||||||
rear_port_model = RearPort
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = FrontPort
|
model = FrontPort
|
||||||
fields = [
|
fields = [
|
||||||
@@ -1611,12 +1630,13 @@ class FrontPortForm(FrontPortFormMixin, ModularDeviceComponentForm):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
# Populate rear port choices
|
|
||||||
if device_id := self.data.get('device') or self.initial.get('device'):
|
if device_id := self.data.get('device') or self.initial.get('device'):
|
||||||
parent_filter = Q(device=device_id)
|
device = Device.objects.get(pk=device_id)
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
self.fields['rear_ports'].choices = self._get_rear_port_choices(parent_filter, self.instance)
|
|
||||||
|
# Populate rear port choices
|
||||||
|
self.fields['rear_ports'].choices = self._get_rear_port_choices(device, self.instance)
|
||||||
|
|
||||||
# Set initial rear port mappings
|
# Set initial rear port mappings
|
||||||
if self.instance.pk:
|
if self.instance.pk:
|
||||||
@@ -1625,6 +1645,27 @@ class FrontPortForm(FrontPortFormMixin, ModularDeviceComponentForm):
|
|||||||
for mapping in PortMapping.objects.filter(front_port_id=self.instance.pk)
|
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):
|
class RearPortForm(ModularDeviceComponentForm):
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
|
|||||||
@@ -211,16 +211,12 @@ def sync_cached_scope_fields(instance, created, **kwargs):
|
|||||||
for model in (Prefix, Cluster, WirelessLAN):
|
for model in (Prefix, Cluster, WirelessLAN):
|
||||||
qs = model.objects.filter(**filters)
|
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:
|
for obj in qs:
|
||||||
# Recompute cache using the same logic as save()
|
# Recompute cache using the same logic as save()
|
||||||
obj.cache_related_objects()
|
obj.cache_related_objects()
|
||||||
objects_to_update.append(obj)
|
obj.save(update_fields=[
|
||||||
|
'_location',
|
||||||
if objects_to_update:
|
'_site',
|
||||||
model.objects.bulk_update(
|
'_site_group',
|
||||||
objects_to_update,
|
'_region',
|
||||||
['_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_width = attrs.NumericAttr('outer_width', unit_accessor='get_outer_unit_display')
|
||||||
outer_height = attrs.NumericAttr('outer_height', 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')
|
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):
|
class RackNumberingPanel(panels.ObjectAttributesPanel):
|
||||||
|
|||||||
@@ -1845,7 +1845,6 @@ class ModuleTypeBulkEditView(generic.BulkEditView):
|
|||||||
class ModuleTypeBulkRenameView(generic.BulkRenameView):
|
class ModuleTypeBulkRenameView(generic.BulkRenameView):
|
||||||
queryset = ModuleType.objects.all()
|
queryset = ModuleType.objects.all()
|
||||||
filterset = filtersets.ModuleTypeFilterSet
|
filterset = filtersets.ModuleTypeFilterSet
|
||||||
field_name = 'model'
|
|
||||||
|
|
||||||
|
|
||||||
@register_model_view(ModuleType, 'bulk_delete', path='delete', detail=False)
|
@register_model_view(ModuleType, 'bulk_delete', path='delete', detail=False)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class ConfigContextProfileSerializer(PrimaryModelSerializer):
|
|||||||
)
|
)
|
||||||
data_file = DataFileSerializer(
|
data_file = DataFileSerializer(
|
||||||
nested=True,
|
nested=True,
|
||||||
required=False
|
read_only=True
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -143,7 +143,7 @@ class ConfigContextSerializer(OwnerMixin, ChangeLogMessageSerializer, ValidatedM
|
|||||||
)
|
)
|
||||||
data_file = DataFileSerializer(
|
data_file = DataFileSerializer(
|
||||||
nested=True,
|
nested=True,
|
||||||
required=False
|
read_only=True
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -4,17 +4,6 @@ from extras.choices import LogLevelChoices
|
|||||||
# Custom fields
|
# Custom fields
|
||||||
CUSTOMFIELD_EMPTY_VALUES = (None, '', [])
|
CUSTOMFIELD_EMPTY_VALUES = (None, '', [])
|
||||||
|
|
||||||
# ImageAttachment
|
|
||||||
IMAGE_ATTACHMENT_IMAGE_FORMATS = {
|
|
||||||
'avif': 'image/avif',
|
|
||||||
'bmp': 'image/bmp',
|
|
||||||
'gif': 'image/gif',
|
|
||||||
'jpeg': 'image/jpeg',
|
|
||||||
'jpg': 'image/jpeg',
|
|
||||||
'png': 'image/png',
|
|
||||||
'webp': 'image/webp',
|
|
||||||
}
|
|
||||||
|
|
||||||
# Template Export
|
# Template Export
|
||||||
DEFAULT_MIME_TYPE = 'text/plain; charset=utf-8'
|
DEFAULT_MIME_TYPE = 'text/plain; charset=utf-8'
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from core.forms.mixins import SyncedDataMixin
|
from core.forms.mixins import SyncedDataMixin
|
||||||
from core.models import ObjectType
|
from core.models import ObjectType
|
||||||
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
|
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
|
||||||
from extras.constants import IMAGE_ATTACHMENT_IMAGE_FORMATS
|
|
||||||
from extras.choices import *
|
from extras.choices import *
|
||||||
from extras.models import *
|
from extras.models import *
|
||||||
from netbox.events import get_event_type_choices
|
from netbox.events import get_event_type_choices
|
||||||
@@ -785,11 +784,8 @@ class ImageAttachmentForm(forms.ModelForm):
|
|||||||
fields = [
|
fields = [
|
||||||
'image', 'name', 'description',
|
'image', 'name', 'description',
|
||||||
]
|
]
|
||||||
# Explicitly set 'image/avif' to support AVIF selection in Firefox
|
help_texts = {
|
||||||
widgets = {
|
'name': _("If no name is specified, the file name will be used.")
|
||||||
'image': forms.ClearableFileInput(
|
|
||||||
attrs={'accept': ','.join(sorted(set(IMAGE_ATTACHMENT_IMAGE_FORMATS.values())))}
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import hashlib
|
|
||||||
|
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
@@ -8,7 +7,7 @@ from rest_framework import status
|
|||||||
|
|
||||||
from core.choices import ManagedFileRootPathChoices
|
from core.choices import ManagedFileRootPathChoices
|
||||||
from core.events import *
|
from core.events import *
|
||||||
from core.models import DataFile, DataSource, ObjectType
|
from core.models import ObjectType
|
||||||
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Rack, Location, RackRole, Site
|
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Rack, Location, RackRole, Site
|
||||||
from extras.choices import *
|
from extras.choices import *
|
||||||
from extras.models import *
|
from extras.models import *
|
||||||
@@ -732,51 +731,6 @@ class ConfigContextProfileTest(APIViewTestCases.APIViewTestCase):
|
|||||||
)
|
)
|
||||||
ConfigContextProfile.objects.bulk_create(profiles)
|
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):
|
class ConfigContextTest(APIViewTestCases.APIViewTestCase):
|
||||||
model = ConfigContext
|
model = ConfigContext
|
||||||
@@ -858,51 +812,6 @@ class ConfigContextTest(APIViewTestCases.APIViewTestCase):
|
|||||||
rendered_context = device.get_config_context()
|
rendered_context = device.get_config_context()
|
||||||
self.assertEqual(rendered_context['bar'], 456)
|
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):
|
class ConfigTemplateTest(APIViewTestCases.APIViewTestCase):
|
||||||
model = ConfigTemplate
|
model = ConfigTemplate
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ from taggit.managers import _TaggableManager
|
|||||||
|
|
||||||
from netbox.context import current_request
|
from netbox.context import current_request
|
||||||
|
|
||||||
from .constants import IMAGE_ATTACHMENT_IMAGE_FORMATS
|
|
||||||
from .validators import CustomValidator
|
from .validators import CustomValidator
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
@@ -79,7 +78,7 @@ def image_upload(instance, filename):
|
|||||||
"""
|
"""
|
||||||
upload_dir = 'image-attachments'
|
upload_dir = 'image-attachments'
|
||||||
default_filename = 'unnamed'
|
default_filename = 'unnamed'
|
||||||
allowed_img_extensions = IMAGE_ATTACHMENT_IMAGE_FORMATS.keys()
|
allowed_img_extensions = ('bmp', 'gif', 'jpeg', 'jpg', 'png', 'webp')
|
||||||
|
|
||||||
# Normalize Windows paths and create a Path object.
|
# Normalize Windows paths and create a Path object.
|
||||||
normalized_filename = str(filename).replace('\\', '/')
|
normalized_filename = str(filename).replace('\\', '/')
|
||||||
|
|||||||
@@ -538,7 +538,7 @@ class VLANFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
|
|||||||
FieldSet('qinq_role', 'qinq_svlan_id', name=_('Q-in-Q/802.1ad')),
|
FieldSet('qinq_role', 'qinq_svlan_id', name=_('Q-in-Q/802.1ad')),
|
||||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||||
)
|
)
|
||||||
selector_fields = ('filter_id', 'q', 'group_id')
|
selector_fields = ('filter_id', 'q', 'site_id')
|
||||||
region_id = DynamicModelMultipleChoiceField(
|
region_id = DynamicModelMultipleChoiceField(
|
||||||
queryset=Region.objects.all(),
|
queryset=Region.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
|
|||||||
@@ -372,8 +372,8 @@ class IPAddressForm(TenancyForm, PrimaryModelForm):
|
|||||||
'virtual_machine_id': instance.assigned_object.virtual_machine.pk,
|
'virtual_machine_id': instance.assigned_object.virtual_machine.pk,
|
||||||
})
|
})
|
||||||
|
|
||||||
# Disable object assignment fields if the IP address is designated as primary or OOB
|
# Disable object assignment fields if the IP address is designated as primary
|
||||||
if self.initial.get('primary_for_parent') or self.initial.get('oob_for_parent'):
|
if self.initial.get('primary_for_parent'):
|
||||||
self.fields['interface'].disabled = True
|
self.fields['interface'].disabled = True
|
||||||
self.fields['vminterface'].disabled = True
|
self.fields['vminterface'].disabled = True
|
||||||
self.fields['fhrpgroup'].disabled = True
|
self.fields['fhrpgroup'].disabled = True
|
||||||
|
|||||||
@@ -940,13 +940,6 @@ class IPAddress(ContactsMixin, PrimaryModel):
|
|||||||
_("Cannot reassign IP address while it is designated as the primary IP for the parent object")
|
_("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
|
# Validate IP status selection
|
||||||
if self.status == IPAddressStatusChoices.STATUS_SLAAC and self.family != 6:
|
if self.status == IPAddressStatusChoices.STATUS_SLAAC and self.family != 6:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from typing import TYPE_CHECKING
|
|||||||
|
|
||||||
import strawberry_django
|
import strawberry_django
|
||||||
from strawberry import ID
|
from strawberry import ID
|
||||||
from strawberry_django import ComparisonFilterLookup, FilterLookup
|
from strawberry_django import FilterLookup
|
||||||
|
|
||||||
from core.graphql.filter_mixins import ChangeLoggingMixin
|
from core.graphql.filter_mixins import ChangeLoggingMixin
|
||||||
from extras.graphql.filter_mixins import CustomFieldsFilterMixin, JournalEntriesFilterMixin, TagsFilterMixin
|
from extras.graphql.filter_mixins import CustomFieldsFilterMixin, JournalEntriesFilterMixin, TagsFilterMixin
|
||||||
@@ -23,7 +23,7 @@ __all__ = (
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class BaseModelFilter:
|
class BaseModelFilter:
|
||||||
id: ComparisonFilterLookup[ID] | None = strawberry_django.filter_field()
|
id: FilterLookup[ID] | None = strawberry_django.filter_field()
|
||||||
|
|
||||||
|
|
||||||
class ChangeLoggedModelFilter(ChangeLoggingMixin, BaseModelFilter):
|
class ChangeLoggedModelFilter(ChangeLoggingMixin, BaseModelFilter):
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ class ObjectAttributesPanel(ObjectPanel, metaclass=ObjectAttributesPanelMeta):
|
|||||||
"""
|
"""
|
||||||
label = name[:1].upper() + name[1:]
|
label = name[:1].upper() + name[1:]
|
||||||
label = label.replace('_', ' ')
|
label = label.replace('_', ' ')
|
||||||
return _(label)
|
return label
|
||||||
|
|
||||||
def get_context(self, context):
|
def get_context(self, context):
|
||||||
# Determine which attributes to display in the panel based on only/exclude args
|
# 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,11 +75,15 @@ export class DynamicTomSelect extends TomSelect {
|
|||||||
load(value: string) {
|
load(value: string) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
|
const currentValue = self.getValue();
|
||||||
|
|
||||||
// Automatically clear any cached options. (Only options included
|
// Automatically clear any cached options. (Only options included
|
||||||
// in the API response should be present.)
|
// in the API response should be present.)
|
||||||
self.clearOptions();
|
self.clearOptions();
|
||||||
|
|
||||||
// Populate the null option (if any) if not searching
|
// Clear user_options to prevent the pre-selected option from being treated specially
|
||||||
|
(self as any).user_options = {};
|
||||||
|
|
||||||
if (self.nullOption && !value) {
|
if (self.nullOption && !value) {
|
||||||
self.addOption(self.nullOption);
|
self.addOption(self.nullOption);
|
||||||
}
|
}
|
||||||
@@ -93,21 +97,33 @@ export class DynamicTomSelect extends TomSelect {
|
|||||||
addClasses(self.wrapper, self.settings.loadingClass);
|
addClasses(self.wrapper, self.settings.loadingClass);
|
||||||
self.loading++;
|
self.loading++;
|
||||||
|
|
||||||
// Make the API request
|
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(apiData => {
|
.then(apiData => {
|
||||||
const results: Dict[] = apiData.results;
|
const results: Dict[] = apiData.results;
|
||||||
const options: Dict[] = [];
|
|
||||||
for (const result of results) {
|
// Add options and set $order to preserve API response order
|
||||||
|
results.forEach((result, index) => {
|
||||||
const option = self.getOptionFromData(result);
|
const option = self.getOptionFromData(result);
|
||||||
options.push(option);
|
self.addOption(option);
|
||||||
|
const key = option[self.settings.valueField as string] as string;
|
||||||
|
if (self.options[key]) {
|
||||||
|
(self.options[key] as any).$order = index;
|
||||||
}
|
}
|
||||||
return options;
|
});
|
||||||
})
|
|
||||||
// Pass the options to the callback function
|
if (self.loading > 0) {
|
||||||
.then(options => {
|
self.loading--;
|
||||||
self.loadCallback(options, []);
|
if (self.loading === 0) {
|
||||||
|
self.wrapper.classList.remove(self.settings.loadingClass as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentValue && !self.items.includes(currentValue as string)) {
|
||||||
|
self.items.push(currentValue as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.refreshOptions(false);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
self.loadCallback([], []);
|
self.loadCallback([], []);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-01-17 05:02+0000\n"
|
"POT-Creation-Date: 2026-01-13 05:05+0000\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@@ -806,7 +806,7 @@ msgstr ""
|
|||||||
#: netbox/circuits/forms/model_forms.py:335
|
#: 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: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: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:863 netbox/dcim/forms/model_forms.py:1917
|
||||||
#: netbox/ipam/forms/bulk_edit.py:380 netbox/ipam/forms/model_forms.py:67
|
#: 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:84 netbox/ipam/forms/model_forms.py:115
|
||||||
#: netbox/ipam/forms/model_forms.py:136 netbox/ipam/forms/model_forms.py:160
|
#: 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/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:399 netbox/dcim/forms/filtersets.py:865
|
||||||
#: netbox/dcim/forms/filtersets.py:1872 netbox/dcim/forms/filtersets.py:1912
|
#: 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:255 netbox/dcim/forms/model_forms.py:1235
|
||||||
#: netbox/dcim/forms/model_forms.py:1697 netbox/dcim/forms/object_import.py:182
|
#: netbox/dcim/forms/model_forms.py:1737 netbox/dcim/forms/object_import.py:182
|
||||||
#: netbox/dcim/tables/devices.py:171 netbox/dcim/tables/devices.py:857
|
#: 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/devices.py:983 netbox/dcim/tables/devicetypes.py:317
|
||||||
#: netbox/dcim/tables/racks.py:117 netbox/extras/filtersets.py:708
|
#: 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/bulk_import.py:258
|
||||||
#: netbox/circuits/forms/model_forms.py:358
|
#: netbox/circuits/forms/model_forms.py:358
|
||||||
#: netbox/circuits/tables/virtual_circuits.py:108
|
#: netbox/circuits/tables/virtual_circuits.py:108
|
||||||
#: netbox/dcim/forms/bulk_import.py:1324 netbox/dcim/forms/model_forms.py:1288
|
#: netbox/dcim/forms/bulk_import.py:1324 netbox/dcim/forms/model_forms.py:1309
|
||||||
#: netbox/dcim/forms/model_forms.py:1557 netbox/dcim/forms/model_forms.py:1738
|
#: netbox/dcim/forms/model_forms.py:1578 netbox/dcim/forms/model_forms.py:1778
|
||||||
#: netbox/dcim/forms/model_forms.py:1773 netbox/dcim/forms/model_forms.py:1898
|
#: netbox/dcim/forms/model_forms.py:1813 netbox/dcim/forms/model_forms.py:1938
|
||||||
#: netbox/dcim/tables/connections.py:65 netbox/dcim/tables/devices.py:1150
|
#: 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/bulk_import.py:319 netbox/ipam/forms/model_forms.py:280
|
||||||
#: netbox/ipam/forms/model_forms.py:289 netbox/ipam/tables/fhrp.py:61
|
#: 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:1866 netbox/dcim/forms/filtersets.py:1907
|
||||||
#: netbox/dcim/forms/filtersets.py:2000 netbox/dcim/forms/filtersets.py:2024
|
#: 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/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:943 netbox/dcim/forms/model_forms.py:1376
|
||||||
#: netbox/dcim/forms/model_forms.py:1849 netbox/dcim/forms/model_forms.py:1922
|
#: netbox/dcim/forms/model_forms.py:1889 netbox/dcim/forms/model_forms.py:1962
|
||||||
#: netbox/dcim/forms/object_create.py:205 netbox/dcim/tables/connections.py:22
|
#: 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/connections.py:41 netbox/dcim/tables/connections.py:60
|
||||||
#: netbox/dcim/tables/devices.py:291 netbox/dcim/tables/devices.py:386
|
#: 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})."
|
msgid "Change logging is not supported for this object type ({type})."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/core/models/config.py:21 netbox/core/models/data.py:284
|
#: netbox/core/models/config.py:21 netbox/core/models/data.py:282
|
||||||
#: netbox/core/models/files.py:29 netbox/core/models/jobs.py:60
|
#: 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/models.py:847 netbox/extras/models/notifications.py:39
|
||||||
#: netbox/extras/models/notifications.py:195
|
#: netbox/extras/models/notifications.py:195
|
||||||
@@ -2541,63 +2541,58 @@ msgstr ""
|
|||||||
msgid "Unknown backend type: {type}"
|
msgid "Unknown backend type: {type}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/core/models/data.py:131
|
#: netbox/core/models/data.py:180
|
||||||
#, 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."
|
msgid "Cannot initiate sync; syncing already in progress."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/core/models/data.py:195
|
#: netbox/core/models/data.py:193
|
||||||
msgid ""
|
msgid ""
|
||||||
"There was an error initializing the backend. A dependency needs to be "
|
"There was an error initializing the backend. A dependency needs to be "
|
||||||
"installed: "
|
"installed: "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/core/models/data.py:288 netbox/core/models/files.py:33
|
#: netbox/core/models/data.py:286 netbox/core/models/files.py:33
|
||||||
#: netbox/netbox/models/features.py:67
|
#: netbox/netbox/models/features.py:67
|
||||||
msgid "last updated"
|
msgid "last updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/core/models/data.py:298 netbox/dcim/models/cables.py:622
|
#: netbox/core/models/data.py:296 netbox/dcim/models/cables.py:622
|
||||||
msgid "path"
|
msgid "path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/core/models/data.py:301
|
#: netbox/core/models/data.py:299
|
||||||
msgid "File path relative to the data source's root"
|
msgid "File path relative to the data source's root"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/core/models/data.py:305 netbox/ipam/models/ip.py:507
|
#: netbox/core/models/data.py:303 netbox/ipam/models/ip.py:507
|
||||||
msgid "size"
|
msgid "size"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/core/models/data.py:308
|
#: netbox/core/models/data.py:306
|
||||||
msgid "hash"
|
msgid "hash"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/core/models/data.py:312
|
#: netbox/core/models/data.py:310
|
||||||
msgid "Length must be 64 hexadecimal characters."
|
msgid "Length must be 64 hexadecimal characters."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/core/models/data.py:314
|
#: netbox/core/models/data.py:312
|
||||||
msgid "SHA256 hash of the file data"
|
msgid "SHA256 hash of the file data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/core/models/data.py:328
|
#: netbox/core/models/data.py:326
|
||||||
msgid "data file"
|
msgid "data file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/core/models/data.py:329
|
#: netbox/core/models/data.py:327
|
||||||
msgid "data files"
|
msgid "data files"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/core/models/data.py:402
|
#: netbox/core/models/data.py:400
|
||||||
msgid "auto sync record"
|
msgid "auto sync record"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/core/models/data.py:403
|
#: netbox/core/models/data.py:401
|
||||||
msgid "auto sync records"
|
msgid "auto sync records"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3084,8 +3079,8 @@ msgstr ""
|
|||||||
#: netbox/dcim/forms/filtersets.py:768 netbox/dcim/forms/filtersets.py:783
|
#: 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: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: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:523 netbox/dcim/forms/model_forms.py:1227
|
||||||
#: netbox/dcim/forms/model_forms.py:1689 netbox/dcim/forms/object_import.py:177
|
#: netbox/dcim/forms/model_forms.py:1729 netbox/dcim/forms/object_import.py:177
|
||||||
#: netbox/dcim/tables/devices.py:702 netbox/dcim/tables/devices.py:916
|
#: 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/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
|
#: netbox/ipam/forms/bulk_import.py:578 netbox/ipam/forms/model_forms.py:755
|
||||||
@@ -3217,7 +3212,7 @@ msgstr ""
|
|||||||
#: netbox/dcim/choices.py:885 netbox/dcim/choices.py:1351
|
#: 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/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/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/model_forms.py:1590 netbox/netbox/navigation/menu.py:147
|
||||||
#: netbox/netbox/navigation/menu.py:151
|
#: netbox/netbox/navigation/menu.py:151
|
||||||
#: netbox/templates/dcim/interface.html:280
|
#: netbox/templates/dcim/interface.html:280
|
||||||
msgid "Wireless"
|
msgid "Wireless"
|
||||||
@@ -3835,7 +3830,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: netbox/dcim/filtersets.py:1242 netbox/dcim/forms/filtersets.py:906
|
#: 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/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:1935 netbox/dcim/models/devices.py:1307
|
||||||
#: netbox/dcim/models/devices.py:1330 netbox/virtualization/filtersets.py:211
|
#: netbox/dcim/models/devices.py:1330 netbox/virtualization/filtersets.py:211
|
||||||
#: netbox/virtualization/filtersets.py:284
|
#: netbox/virtualization/filtersets.py:284
|
||||||
#: netbox/virtualization/forms/filtersets.py:187
|
#: netbox/virtualization/forms/filtersets.py:187
|
||||||
@@ -4001,7 +3996,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: netbox/dcim/filtersets.py:1942 netbox/dcim/forms/bulk_edit.py:1509
|
#: 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/bulk_import.py:1027 netbox/dcim/forms/filtersets.py:1662
|
||||||
#: netbox/dcim/forms/model_forms.py:1535
|
#: netbox/dcim/forms/model_forms.py:1556
|
||||||
#: netbox/dcim/models/device_components.py:866
|
#: netbox/dcim/models/device_components.py:866
|
||||||
#: netbox/dcim/tables/devices.py:660 netbox/ipam/filtersets.py:345
|
#: netbox/dcim/tables/devices.py:660 netbox/ipam/filtersets.py:345
|
||||||
#: netbox/ipam/filtersets.py:356 netbox/ipam/filtersets.py:489
|
#: netbox/ipam/filtersets.py:356 netbox/ipam/filtersets.py:489
|
||||||
@@ -4060,7 +4055,7 @@ msgid "VLAN Translation Policy (ID)"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/filtersets.py:1970 netbox/dcim/forms/filtersets.py:1633
|
#: netbox/dcim/filtersets.py:1970 netbox/dcim/forms/filtersets.py:1633
|
||||||
#: netbox/dcim/forms/model_forms.py:1552
|
#: netbox/dcim/forms/model_forms.py:1573
|
||||||
#: netbox/dcim/models/device_components.py:668
|
#: netbox/dcim/models/device_components.py:668
|
||||||
#: netbox/ipam/forms/filtersets.py:518 netbox/ipam/forms/model_forms.py:700
|
#: netbox/ipam/forms/filtersets.py:518 netbox/ipam/forms/model_forms.py:700
|
||||||
#: netbox/templates/ipam/vlantranslationpolicy.html:11
|
#: netbox/templates/ipam/vlantranslationpolicy.html:11
|
||||||
@@ -4114,14 +4109,14 @@ msgstr ""
|
|||||||
msgid "Primary MAC address (ID)"
|
msgid "Primary MAC address (ID)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/filtersets.py:2057 netbox/dcim/forms/model_forms.py:1539
|
#: netbox/dcim/filtersets.py:2057 netbox/dcim/forms/model_forms.py:1560
|
||||||
#: netbox/virtualization/filtersets.py:295
|
#: netbox/virtualization/filtersets.py:295
|
||||||
#: netbox/virtualization/forms/model_forms.py:302
|
#: netbox/virtualization/forms/model_forms.py:302
|
||||||
msgid "Primary MAC address"
|
msgid "Primary MAC address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/filtersets.py:2079 netbox/dcim/filtersets.py:2091
|
#: 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:1915
|
||||||
#: netbox/templates/dcim/virtualdevicecontext.html:15
|
#: netbox/templates/dcim/virtualdevicecontext.html:15
|
||||||
msgid "Virtual Device Context"
|
msgid "Virtual Device Context"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -4243,7 +4238,7 @@ msgstr ""
|
|||||||
#: netbox/dcim/forms/filtersets.py:1917 netbox/dcim/forms/model_forms.py:211
|
#: 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: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: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/model_forms.py:1240 netbox/dcim/forms/model_forms.py:1742
|
||||||
#: netbox/dcim/forms/object_import.py:188 netbox/dcim/tables/devices.py:99
|
#: 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/devices.py:174 netbox/dcim/tables/devices.py:986
|
||||||
#: netbox/dcim/tables/devicetypes.py:86 netbox/dcim/tables/devicetypes.py:321
|
#: netbox/dcim/tables/devicetypes.py:86 netbox/dcim/tables/devicetypes.py:321
|
||||||
@@ -4421,7 +4416,7 @@ msgstr ""
|
|||||||
#: netbox/dcim/forms/filtersets.py:524 netbox/dcim/forms/filtersets.py:667
|
#: 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/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:432 netbox/dcim/forms/model_forms.py:767
|
||||||
#: netbox/dcim/forms/model_forms.py:1770
|
#: netbox/dcim/forms/model_forms.py:1810
|
||||||
#: netbox/templates/dcim/device_edit.html:22
|
#: netbox/templates/dcim/device_edit.html:22
|
||||||
msgid "Hardware"
|
msgid "Hardware"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -4447,8 +4442,8 @@ msgstr ""
|
|||||||
#: netbox/dcim/forms/bulk_edit.py:531 netbox/dcim/forms/model_forms.py:373
|
#: 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: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: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:1120 netbox/dcim/forms/model_forms.py:1181
|
||||||
#: netbox/dcim/forms/model_forms.py:1178 netbox/dcim/forms/object_create.py:117
|
#: netbox/dcim/forms/model_forms.py:1199 netbox/dcim/forms/object_create.py:117
|
||||||
#: netbox/dcim/tables/devicetypes.py:83 netbox/templates/dcim/devicebay.html:52
|
#: netbox/dcim/tables/devicetypes.py:83 netbox/templates/dcim/devicebay.html:52
|
||||||
#: netbox/templates/dcim/module.html:61
|
#: netbox/templates/dcim/module.html:61
|
||||||
msgid "Device Type"
|
msgid "Device Type"
|
||||||
@@ -4477,7 +4472,7 @@ msgstr ""
|
|||||||
#: netbox/dcim/forms/model_forms.py:431 netbox/dcim/forms/model_forms.py:1003
|
#: 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: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: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:1182 netbox/dcim/forms/model_forms.py:1200
|
||||||
#: netbox/dcim/forms/object_create.py:118 netbox/dcim/tables/modules.py:51
|
#: 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/dcim/tables/modules.py:94 netbox/templates/dcim/module.html:92
|
||||||
#: netbox/templates/dcim/modulebay.html:66
|
#: netbox/templates/dcim/modulebay.html:66
|
||||||
@@ -4661,8 +4656,8 @@ msgid "Allocated power draw (watts)"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/bulk_edit.py:1058 netbox/dcim/forms/bulk_import.py:885
|
#: 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:1060 netbox/dcim/forms/model_forms.py:1446
|
||||||
#: netbox/dcim/forms/model_forms.py:1754 netbox/dcim/forms/object_import.py:56
|
#: netbox/dcim/forms/model_forms.py:1794 netbox/dcim/forms/object_import.py:56
|
||||||
msgid "Power port"
|
msgid "Power port"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4697,7 +4692,7 @@ msgid "Wireless role"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/model_forms.py:766
|
#: 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/model_forms.py:1391 netbox/dcim/tables/devices.py:328
|
||||||
#: netbox/templates/dcim/consoleport.html:24
|
#: netbox/templates/dcim/consoleport.html:24
|
||||||
#: netbox/templates/dcim/consoleserverport.html:24
|
#: netbox/templates/dcim/consoleserverport.html:24
|
||||||
#: netbox/templates/dcim/frontport.html:24
|
#: netbox/templates/dcim/frontport.html:24
|
||||||
@@ -4715,7 +4710,7 @@ msgstr ""
|
|||||||
msgid "LAG"
|
msgid "LAG"
|
||||||
msgstr ""
|
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:1473
|
||||||
msgid "Virtual device contexts"
|
msgid "Virtual device contexts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4744,7 +4739,7 @@ msgid "Mode"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/bulk_edit.py:1458 netbox/dcim/forms/bulk_import.py:993
|
#: 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:1522 netbox/ipam/forms/bulk_import.py:173
|
||||||
#: netbox/ipam/forms/filtersets.py:568 netbox/ipam/models/vlans.py:93
|
#: netbox/ipam/forms/filtersets.py:568 netbox/ipam/models/vlans.py:93
|
||||||
#: netbox/virtualization/forms/bulk_edit.py:205
|
#: netbox/virtualization/forms/bulk_edit.py:205
|
||||||
#: netbox/virtualization/forms/bulk_import.py:185
|
#: netbox/virtualization/forms/bulk_import.py:185
|
||||||
@@ -4753,7 +4748,7 @@ msgid "VLAN group"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/bulk_edit.py:1467 netbox/dcim/forms/bulk_import.py:1000
|
#: 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:1528 netbox/dcim/tables/devices.py:605
|
||||||
#: netbox/virtualization/forms/bulk_edit.py:213
|
#: netbox/virtualization/forms/bulk_edit.py:213
|
||||||
#: netbox/virtualization/forms/bulk_import.py:192
|
#: netbox/virtualization/forms/bulk_import.py:192
|
||||||
#: netbox/virtualization/forms/model_forms.py:331
|
#: netbox/virtualization/forms/model_forms.py:331
|
||||||
@@ -4761,7 +4756,7 @@ msgid "Untagged VLAN"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/bulk_import.py:1007
|
#: 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:1537 netbox/dcim/tables/devices.py:611
|
||||||
#: netbox/virtualization/forms/bulk_edit.py:221
|
#: netbox/virtualization/forms/bulk_edit.py:221
|
||||||
#: netbox/virtualization/forms/bulk_import.py:199
|
#: netbox/virtualization/forms/bulk_import.py:199
|
||||||
#: netbox/virtualization/forms/model_forms.py:340
|
#: netbox/virtualization/forms/model_forms.py:340
|
||||||
@@ -4777,18 +4772,18 @@ msgid "Remove tagged VLANs"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/bulk_import.py:1020
|
#: 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:1546
|
||||||
#: netbox/virtualization/forms/bulk_import.py:212
|
#: netbox/virtualization/forms/bulk_import.py:212
|
||||||
#: netbox/virtualization/forms/model_forms.py:349
|
#: netbox/virtualization/forms/model_forms.py:349
|
||||||
msgid "Q-in-Q Service VLAN"
|
msgid "Q-in-Q Service VLAN"
|
||||||
msgstr ""
|
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:1509
|
||||||
#: netbox/wireless/forms/filtersets.py:26
|
#: netbox/wireless/forms/filtersets.py:26
|
||||||
msgid "Wireless LAN group"
|
msgid "Wireless LAN group"
|
||||||
msgstr ""
|
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:1514
|
||||||
#: netbox/dcim/tables/devices.py:653 netbox/netbox/navigation/menu.py:153
|
#: netbox/dcim/tables/devices.py:653 netbox/netbox/navigation/menu.py:153
|
||||||
#: netbox/templates/dcim/interface.html:350
|
#: netbox/templates/dcim/interface.html:350
|
||||||
#: netbox/wireless/tables/wirelesslan.py:20
|
#: netbox/wireless/tables/wirelesslan.py:20
|
||||||
@@ -4796,7 +4791,7 @@ msgid "Wireless LANs"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/bulk_edit.py:1528 netbox/dcim/forms/filtersets.py:1550
|
#: 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:1580 netbox/ipam/forms/bulk_edit.py:224
|
||||||
#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/filtersets.py:184
|
#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/filtersets.py:184
|
||||||
#: netbox/netbox/navigation/menu.py:109
|
#: netbox/netbox/navigation/menu.py:109
|
||||||
#: netbox/templates/dcim/interface.html:141
|
#: netbox/templates/dcim/interface.html:141
|
||||||
@@ -4808,18 +4803,18 @@ msgid "Addressing"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/bulk_edit.py:1529 netbox/dcim/forms/filtersets.py:808
|
#: 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:1581
|
||||||
#: netbox/virtualization/forms/model_forms.py:370
|
#: netbox/virtualization/forms/model_forms.py:370
|
||||||
msgid "Operation"
|
msgid "Operation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/bulk_edit.py:1530 netbox/dcim/forms/filtersets.py:1551
|
#: 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/filtersets.py:1677 netbox/dcim/forms/model_forms.py:1104
|
||||||
#: netbox/dcim/forms/model_forms.py:1562
|
#: netbox/dcim/forms/model_forms.py:1583
|
||||||
msgid "PoE"
|
msgid "PoE"
|
||||||
msgstr ""
|
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:1582
|
||||||
#: netbox/templates/dcim/interface.html:105
|
#: netbox/templates/dcim/interface.html:105
|
||||||
#: netbox/virtualization/forms/bulk_edit.py:237
|
#: netbox/virtualization/forms/bulk_edit.py:237
|
||||||
#: netbox/virtualization/forms/model_forms.py:371
|
#: netbox/virtualization/forms/model_forms.py:371
|
||||||
@@ -4827,7 +4822,7 @@ msgid "Related Interfaces"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/bulk_edit.py:1533 netbox/dcim/forms/filtersets.py:1552
|
#: 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:1586
|
||||||
#: netbox/virtualization/forms/bulk_edit.py:240
|
#: netbox/virtualization/forms/bulk_edit.py:240
|
||||||
#: netbox/virtualization/forms/filtersets.py:215
|
#: netbox/virtualization/forms/filtersets.py:215
|
||||||
#: netbox/virtualization/forms/model_forms.py:374
|
#: netbox/virtualization/forms/model_forms.py:374
|
||||||
@@ -5106,13 +5101,13 @@ msgstr ""
|
|||||||
msgid "Electrical phase (for three-phase circuits)"
|
msgid "Electrical phase (for three-phase circuits)"
|
||||||
msgstr ""
|
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:1484
|
||||||
#: netbox/virtualization/forms/bulk_import.py:169
|
#: netbox/virtualization/forms/bulk_import.py:169
|
||||||
#: netbox/virtualization/forms/model_forms.py:310
|
#: netbox/virtualization/forms/model_forms.py:310
|
||||||
msgid "Parent interface"
|
msgid "Parent interface"
|
||||||
msgstr ""
|
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:1492
|
||||||
#: netbox/virtualization/forms/bulk_import.py:176
|
#: netbox/virtualization/forms/bulk_import.py:176
|
||||||
#: netbox/virtualization/forms/model_forms.py:318
|
#: netbox/virtualization/forms/model_forms.py:318
|
||||||
msgid "Bridged interface"
|
msgid "Bridged interface"
|
||||||
@@ -5395,7 +5390,7 @@ msgstr ""
|
|||||||
msgid "Single or three-phase"
|
msgid "Single or three-phase"
|
||||||
msgstr ""
|
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:1895
|
||||||
#: netbox/dcim/ui/panels.py:109
|
#: netbox/dcim/ui/panels.py:109
|
||||||
#: netbox/templates/dcim/virtualdevicecontext.html:30
|
#: netbox/templates/dcim/virtualdevicecontext.html:30
|
||||||
#: netbox/templates/virtualization/virtualmachine.html:56
|
#: netbox/templates/virtualization/virtualmachine.html:56
|
||||||
@@ -5406,7 +5401,7 @@ msgstr ""
|
|||||||
msgid "IPv4 address with mask, e.g. 1.2.3.4/24"
|
msgid "IPv4 address with mask, e.g. 1.2.3.4/24"
|
||||||
msgstr ""
|
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:1904
|
||||||
#: netbox/dcim/ui/panels.py:114
|
#: netbox/dcim/ui/panels.py:114
|
||||||
#: netbox/templates/dcim/virtualdevicecontext.html:41
|
#: netbox/templates/dcim/virtualdevicecontext.html:41
|
||||||
#: netbox/templates/virtualization/virtualmachine.html:72
|
#: netbox/templates/virtualization/virtualmachine.html:72
|
||||||
@@ -5609,7 +5604,7 @@ msgstr ""
|
|||||||
msgid "Mgmt only"
|
msgid "Mgmt only"
|
||||||
msgstr ""
|
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:1568
|
||||||
#: netbox/dcim/models/device_components.py:791
|
#: netbox/dcim/models/device_components.py:791
|
||||||
#: netbox/templates/dcim/interface.html:155
|
#: netbox/templates/dcim/interface.html:155
|
||||||
msgid "WWN"
|
msgid "WWN"
|
||||||
@@ -5710,7 +5705,7 @@ msgstr ""
|
|||||||
msgid "Rear ports"
|
msgid "Rear ports"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/mixins.py:155
|
#: netbox/dcim/forms/mixins.py:158
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"The total number of front port positions ({frontport_count}) must match the "
|
"The total number of front port positions ({frontport_count}) must match the "
|
||||||
@@ -5782,35 +5777,35 @@ msgid ""
|
|||||||
"replaced with the position value when creating a new module."
|
"replaced with the position value when creating a new module."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1231
|
#: netbox/dcim/forms/model_forms.py:1252
|
||||||
msgid "Console port template"
|
msgid "Console port template"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1239
|
#: netbox/dcim/forms/model_forms.py:1260
|
||||||
msgid "Console server port template"
|
msgid "Console server port template"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1247
|
#: netbox/dcim/forms/model_forms.py:1268
|
||||||
msgid "Front port template"
|
msgid "Front port template"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1255
|
#: netbox/dcim/forms/model_forms.py:1276
|
||||||
msgid "Interface template"
|
msgid "Interface template"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1263
|
#: netbox/dcim/forms/model_forms.py:1284
|
||||||
msgid "Power outlet template"
|
msgid "Power outlet template"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1271
|
#: netbox/dcim/forms/model_forms.py:1292
|
||||||
msgid "Power port template"
|
msgid "Power port template"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1279
|
#: netbox/dcim/forms/model_forms.py:1300
|
||||||
msgid "Rear port template"
|
msgid "Rear port template"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1289 netbox/dcim/forms/model_forms.py:1774
|
#: netbox/dcim/forms/model_forms.py:1310 netbox/dcim/forms/model_forms.py:1814
|
||||||
#: netbox/dcim/tables/connections.py:27
|
#: netbox/dcim/tables/connections.py:27
|
||||||
#: netbox/templates/dcim/consoleport.html:17
|
#: netbox/templates/dcim/consoleport.html:17
|
||||||
#: netbox/templates/dcim/consoleserverport.html:73
|
#: netbox/templates/dcim/consoleserverport.html:73
|
||||||
@@ -5818,14 +5813,14 @@ msgstr ""
|
|||||||
msgid "Console Port"
|
msgid "Console Port"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1290 netbox/dcim/forms/model_forms.py:1775
|
#: netbox/dcim/forms/model_forms.py:1311 netbox/dcim/forms/model_forms.py:1815
|
||||||
#: netbox/templates/dcim/consoleport.html:73
|
#: netbox/templates/dcim/consoleport.html:73
|
||||||
#: netbox/templates/dcim/consoleserverport.html:17
|
#: netbox/templates/dcim/consoleserverport.html:17
|
||||||
#: netbox/templates/dcim/frontport.html:106
|
#: netbox/templates/dcim/frontport.html:106
|
||||||
msgid "Console Server Port"
|
msgid "Console Server Port"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1291 netbox/dcim/forms/model_forms.py:1776
|
#: netbox/dcim/forms/model_forms.py:1312 netbox/dcim/forms/model_forms.py:1816
|
||||||
#: netbox/templates/circuits/inc/circuit_termination_fields.html:53
|
#: netbox/templates/circuits/inc/circuit_termination_fields.html:53
|
||||||
#: netbox/templates/dcim/consoleport.html:76
|
#: netbox/templates/dcim/consoleport.html:76
|
||||||
#: netbox/templates/dcim/consoleserverport.html:76
|
#: netbox/templates/dcim/consoleserverport.html:76
|
||||||
@@ -5837,7 +5832,7 @@ msgstr ""
|
|||||||
msgid "Front Port"
|
msgid "Front Port"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1292 netbox/dcim/forms/model_forms.py:1777
|
#: netbox/dcim/forms/model_forms.py:1313 netbox/dcim/forms/model_forms.py:1817
|
||||||
#: netbox/templates/circuits/inc/circuit_termination_fields.html:54
|
#: netbox/templates/circuits/inc/circuit_termination_fields.html:54
|
||||||
#: netbox/templates/dcim/consoleport.html:79
|
#: netbox/templates/dcim/consoleport.html:79
|
||||||
#: netbox/templates/dcim/consoleserverport.html:79
|
#: netbox/templates/dcim/consoleserverport.html:79
|
||||||
@@ -5849,80 +5844,80 @@ msgstr ""
|
|||||||
msgid "Rear Port"
|
msgid "Rear Port"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1293 netbox/dcim/forms/model_forms.py:1778
|
#: netbox/dcim/forms/model_forms.py:1314 netbox/dcim/forms/model_forms.py:1818
|
||||||
#: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:526
|
#: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:526
|
||||||
#: netbox/templates/dcim/poweroutlet.html:58
|
#: netbox/templates/dcim/poweroutlet.html:58
|
||||||
#: netbox/templates/dcim/powerport.html:17
|
#: netbox/templates/dcim/powerport.html:17
|
||||||
msgid "Power Port"
|
msgid "Power Port"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1294 netbox/dcim/forms/model_forms.py:1779
|
#: netbox/dcim/forms/model_forms.py:1315 netbox/dcim/forms/model_forms.py:1819
|
||||||
#: netbox/templates/dcim/poweroutlet.html:17
|
#: netbox/templates/dcim/poweroutlet.html:17
|
||||||
#: netbox/templates/dcim/powerport.html:77
|
#: netbox/templates/dcim/powerport.html:77
|
||||||
msgid "Power Outlet"
|
msgid "Power Outlet"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1296 netbox/dcim/forms/model_forms.py:1781
|
#: netbox/dcim/forms/model_forms.py:1317 netbox/dcim/forms/model_forms.py:1821
|
||||||
msgid "Component Assignment"
|
msgid "Component Assignment"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1342 netbox/dcim/forms/model_forms.py:1828
|
#: netbox/dcim/forms/model_forms.py:1363 netbox/dcim/forms/model_forms.py:1868
|
||||||
msgid "An InventoryItem can only be assigned to a single component."
|
msgid "An InventoryItem can only be assigned to a single component."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1479
|
#: netbox/dcim/forms/model_forms.py:1500
|
||||||
msgid "LAG interface"
|
msgid "LAG interface"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1502
|
#: netbox/dcim/forms/model_forms.py:1523
|
||||||
msgid "Filter VLANs available for assignment by group."
|
msgid "Filter VLANs available for assignment by group."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1671
|
#: netbox/dcim/forms/model_forms.py:1711
|
||||||
msgid "Child Device"
|
msgid "Child Device"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1672
|
#: netbox/dcim/forms/model_forms.py:1712
|
||||||
msgid ""
|
msgid ""
|
||||||
"Child devices must first be created and assigned to the site and rack of the "
|
"Child devices must first be created and assigned to the site and rack of the "
|
||||||
"parent device."
|
"parent device."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1714
|
#: netbox/dcim/forms/model_forms.py:1754
|
||||||
msgid "Console port"
|
msgid "Console port"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1722
|
#: netbox/dcim/forms/model_forms.py:1762
|
||||||
msgid "Console server port"
|
msgid "Console server port"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1730 netbox/dcim/forms/object_import.py:140
|
#: netbox/dcim/forms/model_forms.py:1770 netbox/dcim/forms/object_import.py:140
|
||||||
msgid "Front port"
|
msgid "Front port"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1746
|
#: netbox/dcim/forms/model_forms.py:1786
|
||||||
msgid "Power outlet"
|
msgid "Power outlet"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1762 netbox/dcim/forms/object_import.py:145
|
#: netbox/dcim/forms/model_forms.py:1802 netbox/dcim/forms/object_import.py:145
|
||||||
msgid "Rear port"
|
msgid "Rear port"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1768
|
#: netbox/dcim/forms/model_forms.py:1808
|
||||||
#: netbox/templates/dcim/inventoryitem.html:17
|
#: netbox/templates/dcim/inventoryitem.html:17
|
||||||
msgid "Inventory Item"
|
msgid "Inventory Item"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1837
|
#: netbox/dcim/forms/model_forms.py:1877
|
||||||
#: netbox/templates/dcim/inventoryitemrole.html:15
|
#: netbox/templates/dcim/inventoryitemrole.html:15
|
||||||
msgid "Inventory Item Role"
|
msgid "Inventory Item Role"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1907
|
#: netbox/dcim/forms/model_forms.py:1947
|
||||||
msgid "VM Interface"
|
msgid "VM Interface"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1923 netbox/ipam/forms/filtersets.py:638
|
#: netbox/dcim/forms/model_forms.py:1963 netbox/ipam/forms/filtersets.py:638
|
||||||
#: netbox/ipam/forms/model_forms.py:323 netbox/ipam/tables/vlans.py:171
|
#: netbox/ipam/forms/model_forms.py:323 netbox/ipam/tables/vlans.py:171
|
||||||
#: netbox/templates/virtualization/virtualdisk.html:21
|
#: netbox/templates/virtualization/virtualdisk.html:21
|
||||||
#: netbox/templates/virtualization/virtualmachine.html:12
|
#: netbox/templates/virtualization/virtualmachine.html:12
|
||||||
@@ -5939,7 +5934,7 @@ msgstr ""
|
|||||||
msgid "Virtual Machine"
|
msgid "Virtual Machine"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:1962
|
#: netbox/dcim/forms/model_forms.py:2002
|
||||||
msgid "A MAC address can only be assigned to a single object."
|
msgid "A MAC address can only be assigned to a single object."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -7679,7 +7674,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: netbox/dcim/tables/devices.py:252 netbox/dcim/tables/devices.py:1125
|
#: 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/tables/devicetypes.py:131 netbox/dcim/views.py:1412
|
||||||
#: netbox/dcim/views.py:1749 netbox/dcim/views.py:2578
|
#: netbox/dcim/views.py:1749 netbox/dcim/views.py:2577
|
||||||
#: netbox/netbox/navigation/menu.py:95 netbox/netbox/navigation/menu.py:259
|
#: netbox/netbox/navigation/menu.py:95 netbox/netbox/navigation/menu.py:259
|
||||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:38
|
#: netbox/templates/dcim/buttons/bulk_add_components.html:38
|
||||||
#: netbox/templates/dcim/device/base.html:37
|
#: netbox/templates/dcim/device/base.html:37
|
||||||
@@ -7726,7 +7721,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: netbox/dcim/tables/devices.py:333 netbox/dcim/tables/devicetypes.py:52
|
#: 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/tables/devicetypes.py:146 netbox/dcim/views.py:1487
|
||||||
#: netbox/dcim/views.py:2664 netbox/netbox/navigation/menu.py:104
|
#: netbox/dcim/views.py:2663 netbox/netbox/navigation/menu.py:104
|
||||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:66
|
#: netbox/templates/dcim/buttons/bulk_add_components.html:66
|
||||||
#: netbox/templates/dcim/device/base.html:52
|
#: netbox/templates/dcim/device/base.html:52
|
||||||
#: netbox/templates/dcim/devicetype/base.html:49
|
#: netbox/templates/dcim/devicetype/base.html:49
|
||||||
@@ -7860,7 +7855,7 @@ msgid "Device Count"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:1352
|
#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:1352
|
||||||
#: netbox/dcim/views.py:1689 netbox/dcim/views.py:2513
|
#: netbox/dcim/views.py:1689 netbox/dcim/views.py:2512
|
||||||
#: netbox/netbox/navigation/menu.py:98
|
#: netbox/netbox/navigation/menu.py:98
|
||||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:10
|
#: netbox/templates/dcim/buttons/bulk_add_components.html:10
|
||||||
#: netbox/templates/dcim/device/base.html:25
|
#: netbox/templates/dcim/device/base.html:25
|
||||||
@@ -7871,7 +7866,7 @@ msgid "Console Ports"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1367
|
#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1367
|
||||||
#: netbox/dcim/views.py:1704 netbox/dcim/views.py:2529
|
#: netbox/dcim/views.py:1704 netbox/dcim/views.py:2528
|
||||||
#: netbox/netbox/navigation/menu.py:99
|
#: netbox/netbox/navigation/menu.py:99
|
||||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:17
|
#: netbox/templates/dcim/buttons/bulk_add_components.html:17
|
||||||
#: netbox/templates/dcim/device/base.html:28
|
#: netbox/templates/dcim/device/base.html:28
|
||||||
@@ -7882,7 +7877,7 @@ msgid "Console Server Ports"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1382
|
#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1382
|
||||||
#: netbox/dcim/views.py:1719 netbox/dcim/views.py:2545
|
#: netbox/dcim/views.py:1719 netbox/dcim/views.py:2544
|
||||||
#: netbox/netbox/navigation/menu.py:100
|
#: netbox/netbox/navigation/menu.py:100
|
||||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:24
|
#: netbox/templates/dcim/buttons/bulk_add_components.html:24
|
||||||
#: netbox/templates/dcim/device/base.html:31
|
#: netbox/templates/dcim/device/base.html:31
|
||||||
@@ -7893,7 +7888,7 @@ msgid "Power Ports"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1397
|
#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1397
|
||||||
#: netbox/dcim/views.py:1734 netbox/dcim/views.py:2561
|
#: netbox/dcim/views.py:1734 netbox/dcim/views.py:2560
|
||||||
#: netbox/netbox/navigation/menu.py:101
|
#: netbox/netbox/navigation/menu.py:101
|
||||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:31
|
#: netbox/templates/dcim/buttons/bulk_add_components.html:31
|
||||||
#: netbox/templates/dcim/device/base.html:34
|
#: netbox/templates/dcim/device/base.html:34
|
||||||
@@ -7904,7 +7899,7 @@ msgid "Power Outlets"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1427
|
#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1427
|
||||||
#: netbox/dcim/views.py:1764 netbox/dcim/views.py:2600
|
#: netbox/dcim/views.py:1764 netbox/dcim/views.py:2599
|
||||||
#: netbox/netbox/navigation/menu.py:96
|
#: netbox/netbox/navigation/menu.py:96
|
||||||
#: netbox/templates/dcim/device/base.html:40
|
#: netbox/templates/dcim/device/base.html:40
|
||||||
#: netbox/templates/dcim/devicetype/base.html:37
|
#: netbox/templates/dcim/devicetype/base.html:37
|
||||||
@@ -7914,7 +7909,7 @@ msgid "Front Ports"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1442
|
#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1442
|
||||||
#: netbox/dcim/views.py:1779 netbox/dcim/views.py:2616
|
#: netbox/dcim/views.py:1779 netbox/dcim/views.py:2615
|
||||||
#: netbox/netbox/navigation/menu.py:97
|
#: netbox/netbox/navigation/menu.py:97
|
||||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:45
|
#: netbox/templates/dcim/buttons/bulk_add_components.html:45
|
||||||
#: netbox/templates/dcim/device/base.html:43
|
#: netbox/templates/dcim/device/base.html:43
|
||||||
@@ -7925,7 +7920,7 @@ msgid "Rear Ports"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1472
|
#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1472
|
||||||
#: netbox/dcim/views.py:2648 netbox/netbox/navigation/menu.py:103
|
#: netbox/dcim/views.py:2647 netbox/netbox/navigation/menu.py:103
|
||||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:52
|
#: netbox/templates/dcim/buttons/bulk_add_components.html:52
|
||||||
#: netbox/templates/dcim/device/base.html:49
|
#: netbox/templates/dcim/device/base.html:49
|
||||||
#: netbox/templates/dcim/devicetype/base.html:46
|
#: netbox/templates/dcim/devicetype/base.html:46
|
||||||
@@ -7933,7 +7928,7 @@ msgid "Device Bays"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1457
|
#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1457
|
||||||
#: netbox/dcim/views.py:1794 netbox/dcim/views.py:2632
|
#: netbox/dcim/views.py:1794 netbox/dcim/views.py:2631
|
||||||
#: netbox/netbox/navigation/menu.py:102
|
#: netbox/netbox/navigation/menu.py:102
|
||||||
#: netbox/templates/dcim/buttons/bulk_add_components.html:59
|
#: netbox/templates/dcim/buttons/bulk_add_components.html:59
|
||||||
#: netbox/templates/dcim/device/base.html:46
|
#: netbox/templates/dcim/device/base.html:46
|
||||||
@@ -8072,13 +8067,13 @@ msgstr ""
|
|||||||
msgid "Reservations"
|
msgid "Reservations"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/views.py:2459 netbox/netbox/navigation/menu.py:213
|
#: netbox/dcim/views.py:2458 netbox/netbox/navigation/menu.py:213
|
||||||
#: netbox/templates/ipam/ipaddress.html:118
|
#: netbox/templates/ipam/ipaddress.html:118
|
||||||
#: netbox/templates/virtualization/virtualmachine.html:160
|
#: netbox/templates/virtualization/virtualmachine.html:160
|
||||||
msgid "Application Services"
|
msgid "Application Services"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/views.py:2677 netbox/extras/forms/filtersets.py:427
|
#: netbox/dcim/views.py:2676 netbox/extras/forms/filtersets.py:427
|
||||||
#: netbox/extras/forms/model_forms.py:691
|
#: netbox/extras/forms/model_forms.py:691
|
||||||
#: netbox/templates/extras/configcontext.html:10
|
#: netbox/templates/extras/configcontext.html:10
|
||||||
#: netbox/virtualization/forms/model_forms.py:225
|
#: netbox/virtualization/forms/model_forms.py:225
|
||||||
@@ -8086,41 +8081,41 @@ msgstr ""
|
|||||||
msgid "Config Context"
|
msgid "Config Context"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/views.py:2688 netbox/virtualization/views.py:410
|
#: netbox/dcim/views.py:2687 netbox/virtualization/views.py:410
|
||||||
msgid "Render Config"
|
msgid "Render Config"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/views.py:2701 netbox/extras/tables/tables.py:713
|
#: netbox/dcim/views.py:2700 netbox/extras/tables/tables.py:713
|
||||||
#: netbox/netbox/navigation/menu.py:256 netbox/netbox/navigation/menu.py:258
|
#: netbox/netbox/navigation/menu.py:256 netbox/netbox/navigation/menu.py:258
|
||||||
#: netbox/virtualization/views.py:224
|
#: netbox/virtualization/views.py:224
|
||||||
msgid "Virtual Machines"
|
msgid "Virtual Machines"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/views.py:3510
|
#: netbox/dcim/views.py:3509
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Installed device {device} in bay {device_bay}."
|
msgid "Installed device {device} in bay {device_bay}."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/views.py:3551
|
#: netbox/dcim/views.py:3550
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Removed device {device} from bay {device_bay}."
|
msgid "Removed device {device} from bay {device_bay}."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/views.py:3664 netbox/ipam/tables/ip.py:178
|
#: netbox/dcim/views.py:3663 netbox/ipam/tables/ip.py:178
|
||||||
msgid "Children"
|
msgid "Children"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/views.py:4137
|
#: netbox/dcim/views.py:4136
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Added member <a href=\"{url}\">{device}</a>"
|
msgid "Added member <a href=\"{url}\">{device}</a>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/views.py:4182
|
#: netbox/dcim/views.py:4181
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Unable to remove master device {device} from the virtual chassis."
|
msgid "Unable to remove master device {device} from the virtual chassis."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/views.py:4193
|
#: netbox/dcim/views.py:4192
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Removed {device} from virtual chassis {chassis}"
|
msgid "Removed {device} from virtual chassis {chassis}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -11245,13 +11240,7 @@ msgid ""
|
|||||||
"parent object"
|
"parent object"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:947
|
#: netbox/ipam/models/ip.py:946
|
||||||
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"
|
msgid "Only IPv6 addresses can be assigned SLAAC status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -12500,8 +12489,8 @@ msgstr ""
|
|||||||
msgid "Delete Selected"
|
msgid "Delete Selected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/netbox/plugins/navigation.py:53
|
#: netbox/netbox/plugins/navigation.py:55
|
||||||
#: netbox/netbox/plugins/navigation.py:89
|
#: netbox/netbox/plugins/navigation.py:88
|
||||||
msgid "Permissions must be passed as a tuple or list."
|
msgid "Permissions must be passed as a tuple or list."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -12509,7 +12498,7 @@ msgstr ""
|
|||||||
msgid "Buttons must be passed as a tuple or list."
|
msgid "Buttons must be passed as a tuple or list."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/netbox/plugins/navigation.py:95
|
#: netbox/netbox/plugins/navigation.py:92
|
||||||
msgid "Button color must be a choice within ButtonColorChoices."
|
msgid "Button color must be a choice within ButtonColorChoices."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -16587,7 +16576,7 @@ msgstr ""
|
|||||||
msgid "Missing required value for static query param: '{static_params}'"
|
msgid "Missing required value for static query param: '{static_params}'"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/utilities/forms/widgets/modifiers.py:141
|
#: netbox/utilities/forms/widgets/modifiers.py:111
|
||||||
msgid "(automatically set)"
|
msgid "(automatically set)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from utilities.forms.widgets.apiselect import APISelect, APISelectMultiple
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'FilterModifierWidget',
|
'FilterModifierWidget',
|
||||||
'MODIFIER_EMPTY_FALSE',
|
'MODIFIER_EMPTY_FALSE',
|
||||||
@@ -96,37 +94,9 @@ class FilterModifierWidget(forms.Widget):
|
|||||||
# to the original widget before rendering
|
# to the original widget before rendering
|
||||||
self.original_widget.attrs.update(self.attrs)
|
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
|
# Get context from the original widget
|
||||||
original_context = self.original_widget.get_context(name, value, attrs)
|
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
|
# Build our wrapper context
|
||||||
context = super().get_context(name, value, attrs)
|
context = super().get_context(name, value, attrs)
|
||||||
context['widget']['original_widget'] = original_context['widget']
|
context['widget']['original_widget'] = original_context['widget']
|
||||||
|
|||||||
16
scripts/git-hooks/pre-commit
Executable file
16
scripts/git-hooks/pre-commit
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/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