Compare commits

...

11 Commits

Author SHA1 Message Date
Jeremy Stretch
fa8a9ef9de Release v4.4.10
Some checks failed
CI / build (20.x, 3.10) (push) Has been cancelled
CI / build (20.x, 3.11) (push) Has been cancelled
CI / build (20.x, 3.12) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2026-01-06 12:30:03 -05:00
Jeremy Stretch
6beb079b97 Revert "Fixed #20950: Add missing module and device properties in module-bay (#21005)"
This reverts commit 860db9590b.
2026-01-06 10:38:41 -05:00
github-actions
c8aad24a1b Update source translation strings
Some checks failed
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2026-01-06 05:04:58 +00:00
bctiemann
42bd876604 Merge pull request #21072 from netbox-community/21071-exception-request-url
Some checks failed
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
CI / build (20.x, 3.10) (push) Has been cancelled
CI / build (20.x, 3.11) (push) Has been cancelled
CI / build (20.x, 3.12) (push) Has been cancelled
Lock threads / lock (push) Has been cancelled
Close stale issues/PRs / stale (push) Has been cancelled
Close incomplete issues / stale (push) Has been cancelled
Update translation strings / makemessages (push) Has been cancelled
Closes #21071: Include the request method & URL when displaying a server error
2026-01-05 20:20:46 -05:00
bctiemann
f903442cb9 Merge pull request #21065 from netbox-community/21049-clean-stale-cf-data
Fixes #21049: Remove stale custom field data during object validation
2026-01-05 20:19:46 -05:00
Jason Novinger
5a64cb712d Fixes #21064: Ensures that extra choices preserve nested colons 2026-01-05 16:38:16 -05:00
Jason Novinger
4d90d559be Fix permission constraint example error 2026-01-05 16:33:21 -05:00
Jeremy Stretch
19de058f94 Closes #21071: Include the request method & URL when displaying a server error 2026-01-05 16:09:39 -05:00
Jeremy Stretch
dc00e19c3c Fixes #21063: Check for duplicate choice values when validating a custom field choice set (#21066) 2026-01-05 13:10:04 -06:00
Jeremy Stretch
6ed6da49d9 Update test 2026-01-05 11:00:54 -05:00
Jeremy Stretch
bc26529be8 Fixes #21049: Remove stale custom field data during object validation 2026-01-05 09:49:32 -05:00
51 changed files with 8942 additions and 5391 deletions

View File

@@ -15,7 +15,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
placeholder: v4.4.9
placeholder: v4.4.10
validations:
required: true
- type: dropdown

View File

@@ -27,7 +27,7 @@ body:
attributes:
label: NetBox Version
description: What version of NetBox are you currently running?
placeholder: v4.4.9
placeholder: v4.4.10
validations:
required: true
- type: dropdown

File diff suppressed because it is too large Load Diff

View File

@@ -88,7 +88,7 @@ While permissions are typically assigned to specific groups and/or users, it is
### Viewing Objects
Object-based permissions work by filtering the database query generated by a user's request to restrict the set of objects returned. When a request is received, NetBox first determines whether the user is authenticated and has been granted to perform the requested action. For example, if the requested URL is `/dcim/devices/`, NetBox will check for the `dcim.view_device` permission. If the user has not been assigned this permission (either directly or via a group assignment), NetBox will return a 403 (forbidden) HTTP response.
Object-based permissions work by filtering the database query generated by a user's request to restrict the set of objects returned. When a request is received, NetBox first determines whether the user is authenticated and has been granted permission to perform the requested action. For example, if the requested URL is `/dcim/devices/`, NetBox will check for the `dcim.view_device` permission. If the user has not been assigned this permission (either directly or via a group assignment), NetBox will return a 403 (forbidden) HTTP response.
If the permission _has_ been granted, NetBox will compile any specified constraints for the model and action. For example, suppose two permissions have been assigned to the user granting view access to the device model, with the following constraints:
@@ -102,9 +102,9 @@ If the permission _has_ been granted, NetBox will compile any specified constrai
This grants the user access to view any device that is assigned to a site named NYC1 or NYC2, **or** which has a status of "offline" and has no tenant assigned. These constraints are equivalent to the following ORM query:
```no-highlight
Site.objects.filter(
Device.objects.filter(
Q(site__name__in=['NYC1', 'NYC2']),
Q(status='active', tenant__isnull=True)
Q(status='offline', tenant__isnull=True)
)
```

View File

@@ -1,5 +1,25 @@
# NetBox v4.4
## v4.4.10 (2026-01-06)
### Enhancements
* [#20953](https://github.com/netbox-community/netbox/issues/20953) - Show reverse bridge relationships on interface detail pages
* [#21071](https://github.com/netbox-community/netbox/issues/21071) - Include request method & URL when displaying server errors
### Bug Fixes
* [#19506](https://github.com/netbox-community/netbox/issues/19506) - Add filter forms for component templates to ensure object selector support
* [#20044](https://github.com/netbox-community/netbox/issues/20044) - Fix dark mode support for rack elevations
* [#20320](https://github.com/netbox-community/netbox/issues/20320) - Restore support for selecting related interfaces when bulk editing device interfaces
* [#20817](https://github.com/netbox-community/netbox/issues/20817) - Re-enable sync button when disabling scheduled syncing for a data source
* [#21045](https://github.com/netbox-community/netbox/issues/21045) - Fix `ValueError` exception when saving a site with an assigned prefix
* [#21049](https://github.com/netbox-community/netbox/issues/21049) - Ignore stale custom field data when validating an object
* [#21063](https://github.com/netbox-community/netbox/issues/21063) - Check for duplicate choice values when validating a custom field choice set
* [#21064](https://github.com/netbox-community/netbox/issues/21064) - Ensures that extra choices in custom field choice sets preserve escaped colons
---
## v4.4.9 (2025-12-23)
### Enhancements

View File

@@ -351,14 +351,14 @@ class ModuleBaySerializer(NetBoxModelSerializer):
device = DeviceSerializer(nested=True)
module = ModuleSerializer(
nested=True,
fields=('id', 'url', 'display', 'device', 'module_bay'),
fields=('id', 'url', 'display'),
required=False,
allow_null=True,
default=None
)
installed_module = ModuleSerializer(
nested=True,
fields=('id', 'url', 'display', 'device', 'module_bay', 'serial', 'description'),
fields=('id', 'url', 'display', 'serial', 'description'),
required=False,
allow_null=True
)

View File

@@ -189,22 +189,22 @@ class CustomFieldChoiceSetForm(ChangelogMessageMixin, forms.ModelForm):
# if standardize these, we can simplify this code
# Convert extra_choices Array Field from model to CharField for form
if 'extra_choices' in self.initial and self.initial['extra_choices']:
extra_choices = self.initial['extra_choices']
if extra_choices := self.initial.get('extra_choices', None):
if isinstance(extra_choices, str):
extra_choices = [extra_choices]
choices = ""
choices = []
for choice in extra_choices:
# Setup choices in Add Another use case
if isinstance(choice, str):
choice_str = ":".join(choice.replace("'", "").replace(" ", "")[1:-1].split(","))
choices += choice_str + "\n"
choices.append(choice_str)
# Setup choices in Edit use case
elif isinstance(choice, list):
choice_str = ":".join(choice)
choices += choice_str + "\n"
value = choice[0].replace(':', '\\:')
label = choice[1].replace(':', '\\:')
choices.append(f'{value}:{label}')
self.initial['extra_choices'] = choices
self.initial['extra_choices'] = '\n'.join(choices)
def clean_extra_choices(self):
data = []

View File

@@ -878,6 +878,16 @@ class CustomFieldChoiceSet(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel
if not self.base_choices and not self.extra_choices:
raise ValidationError(_("Must define base or extra choices."))
# Check for duplicate values in extra_choices
choice_values = [c[0] for c in self.extra_choices] if self.extra_choices else []
if len(set(choice_values)) != len(choice_values):
# At least one duplicate value is present. Find the first one and raise an error.
_seen = []
for value in choice_values:
if value in _seen:
raise ValidationError(_("Duplicate value '{value}' found in extra choices.").format(value=value))
_seen.append(value)
# Check whether any choices have been removed. If so, check whether any of the removed
# choices are still set in custom field data for any object.
original_choices = set([

View File

@@ -1506,19 +1506,18 @@ class CustomFieldModelTest(TestCase):
def test_invalid_data(self):
"""
Setting custom field data for a non-applicable (or non-existent) CustomField should raise a ValidationError.
Any invalid or stale custom field data should be removed from the instance.
"""
site = Site(name='Test Site', slug='test-site')
# Set custom field data
site.custom_field_data['foo'] = 'abc'
site.custom_field_data['bar'] = 'def'
with self.assertRaises(ValidationError):
site.clean()
del site.custom_field_data['bar']
site.clean()
self.assertIn('foo', site.custom_field_data)
self.assertNotIn('bar', site.custom_field_data)
def test_missing_required_field(self):
"""
Check that a ValidationError is raised if any required custom fields are not present.

View File

@@ -5,6 +5,7 @@ from dcim.forms import SiteForm
from dcim.models import Site
from extras.choices import CustomFieldTypeChoices
from extras.forms import SavedFilterForm
from extras.forms.model_forms import CustomFieldChoiceSetForm
from extras.models import CustomField, CustomFieldChoiceSet
@@ -90,6 +91,31 @@ class CustomFieldModelFormTest(TestCase):
self.assertIsNone(instance.custom_field_data[field_type])
class CustomFieldChoiceSetFormTest(TestCase):
def test_escaped_colons_preserved_on_edit(self):
choice_set = CustomFieldChoiceSet.objects.create(
name='Test Choice Set',
extra_choices=[['foo:bar', 'label'], ['value', 'label:with:colons']]
)
form = CustomFieldChoiceSetForm(instance=choice_set)
initial_choices = form.initial['extra_choices']
# colons are re-escaped
self.assertEqual(initial_choices, 'foo\\:bar:label\nvalue:label\\:with\\:colons')
form = CustomFieldChoiceSetForm(
{'name': choice_set.name, 'extra_choices': initial_choices},
instance=choice_set
)
self.assertTrue(form.is_valid())
updated = form.save()
# cleaned extra choices are correct, which does actually mean a list of tuples
self.assertEqual(updated.extra_choices, [('foo:bar', 'label'), ('value', 'label:with:colons')])
class SavedFilterFormTest(TestCase):
def test_basic_submit(self):

View File

@@ -288,12 +288,13 @@ class CustomFieldsMixin(models.Model):
cf.name: cf for cf in CustomField.objects.get_for_model(self)
}
# Remove any stale custom field data
self.custom_field_data = {
k: v for k, v in self.custom_field_data.items() if k in custom_fields.keys()
}
# Validate all field values
for field_name, value in self.custom_field_data.items():
if field_name not in custom_fields:
raise ValidationError(_("Unknown field name '{name}' in custom field data.").format(
name=field_name
))
try:
custom_fields[field_name].validate(value)
except ValidationError as e:

View File

@@ -52,6 +52,7 @@ def handler_500(request, template_name=ERROR_500_TEMPLATE_NAME):
type_, error = sys.exc_info()[:2]
return HttpResponseServerError(template.render({
'request': request,
'error': error,
'exception': str(type_),
'netbox_version': settings.RELEASE.full_version,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -27,10 +27,10 @@
"bootstrap": "5.3.8",
"clipboard": "2.0.11",
"flatpickr": "4.6.13",
"gridstack": "12.4.1",
"gridstack": "12.4.2",
"htmx.org": "2.0.8",
"query-string": "9.3.1",
"sass": "1.97.1",
"sass": "1.97.2",
"tom-select": "2.4.3",
"typeface-inter": "3.18.1",
"typeface-roboto-mono": "1.1.13"

View File

@@ -2178,10 +2178,10 @@ graphql@16.10.0:
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.10.0.tgz#24c01ae0af6b11ea87bf55694429198aaa8e220c"
integrity sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==
gridstack@12.4.1:
version "12.4.1"
resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-12.4.1.tgz#4a44511e5da33016e731f00bee279bed550d4ab9"
integrity sha512-dYBNVEDw2zwnz0bCDouHk8rMclrMoMn4r6rtNyyWSeYsV3RF8QV2KFRTj4c86T2FsZPr3iQv+/LD/ae29FcpHQ==
gridstack@12.4.2:
version "12.4.2"
resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-12.4.2.tgz#188de180b6cda77e48b1414aac1d778a38f48f04"
integrity sha512-aXbJrQpi3LwpYXYOr4UriPM5uc/dPcjK01SdOE5PDpx2vi8tnLhU7yBg/1i4T59UhNkG/RBfabdFUObuN+gMnw==
has-bigints@^1.0.1, has-bigints@^1.0.2:
version "1.0.2"
@@ -3190,10 +3190,10 @@ safe-regex-test@^1.1.0:
es-errors "^1.3.0"
is-regex "^1.2.1"
sass@1.97.1:
version "1.97.1"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.97.1.tgz#f36e492baf8ccdd08d591b58d3d8b53ea35ab905"
integrity sha512-uf6HoO8fy6ClsrShvMgaKUn14f2EHQLQRtpsZZLeU/Mv0Q1K5P0+x2uvH6Cub39TVVbWNSrraUhDAoFph6vh0A==
sass@1.97.2:
version "1.97.2"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.97.2.tgz#e515a319092fd2c3b015228e3094b40198bff0da"
integrity sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==
dependencies:
chokidar "^4.0.0"
immutable "^5.0.2"

View File

@@ -1,3 +1,3 @@
version: "4.4.9"
version: "4.4.10"
edition: "Community"
published: "2025-12-23"
published: "2026-01-06"

View File

@@ -35,6 +35,12 @@
{% trans "Plugins" %}: {% for plugin, version in plugins.items %}
{{ plugin }}: {{ version }}{% empty %}{% trans "None installed" %}{% endfor %}
</pre>
<p>
{% trans "The request which yielded the above error is shown below:" %}
</p>
<p>
<code>{{ request.method }} {{ request.build_absolute_uri }}</code>
</p>
<p>
{% trans "If further assistance is required, please post to the" %} <a href="https://github.com/netbox-community/netbox/discussions">{% trans "NetBox discussion forum" %}</a> {% trans "on GitHub" %}.
</p>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-01-01 05:06+0000\n"
"POT-Creation-Date: 2026-01-06 05:04+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"
@@ -128,7 +128,7 @@ msgid "Decommissioned"
msgstr ""
#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1927
#: netbox/dcim/tables/devices.py:1178 netbox/templates/dcim/interface.html:135
#: netbox/dcim/tables/devices.py:1178 netbox/templates/dcim/interface.html:148
#: netbox/templates/virtualization/vminterface.html:83
#: netbox/tenancy/choices.py:17
msgid "Primary"
@@ -147,7 +147,7 @@ msgstr ""
msgid "Inactive"
msgstr ""
#: netbox/circuits/choices.py:107 netbox/templates/dcim/interface.html:275
#: netbox/circuits/choices.py:107 netbox/templates/dcim/interface.html:288
#: netbox/vpn/choices.py:63
msgid "Peer"
msgstr ""
@@ -644,7 +644,7 @@ msgstr ""
#: netbox/templates/circuits/virtualcircuit.html:23
#: netbox/templates/circuits/virtualcircuittermination.html:26
#: netbox/templates/dcim/inc/cable_termination.html:58
#: netbox/templates/dcim/interface.html:166
#: netbox/templates/dcim/interface.html:179
msgid "Provider"
msgstr ""
@@ -722,8 +722,8 @@ msgstr ""
#: netbox/templates/dcim/consoleserverport.html:36
#: netbox/templates/dcim/frontport.html:36
#: netbox/templates/dcim/interface.html:46
#: netbox/templates/dcim/interface.html:226
#: netbox/templates/dcim/interface.html:368
#: netbox/templates/dcim/interface.html:239
#: netbox/templates/dcim/interface.html:381
#: netbox/templates/dcim/powerfeed.html:32
#: netbox/templates/dcim/poweroutlet.html:36
#: netbox/templates/dcim/powerport.html:36
@@ -1065,7 +1065,7 @@ msgstr ""
#: netbox/circuits/forms/model_forms.py:185
#: netbox/templates/circuits/inc/circuit_termination_fields.html:55
#: netbox/templates/dcim/frontport.html:121
#: netbox/templates/dcim/interface.html:250
#: netbox/templates/dcim/interface.html:263
#: netbox/templates/dcim/rearport.html:111
msgid "Circuit Termination"
msgstr ""
@@ -1127,8 +1127,8 @@ msgstr ""
#: netbox/templates/circuits/virtualcircuittermination.html:42
#: netbox/templates/dcim/device.html:188
#: netbox/templates/dcim/inc/panels/inventory_items.html:20
#: netbox/templates/dcim/interface.html:178
#: netbox/templates/dcim/interface.html:280
#: netbox/templates/dcim/interface.html:191
#: netbox/templates/dcim/interface.html:293
#: netbox/templates/dcim/inventoryitem.html:40
#: netbox/templates/dcim/rack.html:49 netbox/templates/ipam/ipaddress.html:41
#: netbox/templates/ipam/iprange.html:57 netbox/templates/ipam/prefix.html:73
@@ -1242,8 +1242,8 @@ msgstr ""
#: netbox/templates/circuits/virtualcircuittermination.html:60
#: netbox/templates/dcim/frontport.html:106
#: netbox/templates/dcim/interface.html:27
#: netbox/templates/dcim/interface.html:241
#: netbox/templates/dcim/interface.html:367
#: netbox/templates/dcim/interface.html:254
#: netbox/templates/dcim/interface.html:380
#: netbox/templates/dcim/rearport.html:102
#: netbox/templates/virtualization/vminterface.html:18
#: netbox/templates/vpn/tunneltermination.html:31
@@ -1403,7 +1403,7 @@ msgstr ""
#: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:94
#: netbox/ipam/tables/vlans.py:205
#: netbox/templates/circuits/circuitgroupassignment.html:22
#: netbox/templates/dcim/interface.html:341 netbox/templates/dcim/site.html:37
#: netbox/templates/dcim/interface.html:354 netbox/templates/dcim/site.html:37
#: netbox/templates/ipam/inc/panels/fhrp_groups.html:23
#: netbox/templates/ipam/vlan.html:27 netbox/templates/tenancy/tenant.html:20
#: netbox/templates/users/group.html:6 netbox/templates/users/group.html:14
@@ -1769,7 +1769,7 @@ msgstr ""
#: netbox/templates/dcim/inc/interface_vlans_table.html:5
#: netbox/templates/dcim/inc/panels/inventory_items.html:18
#: netbox/templates/dcim/interface.html:38
#: netbox/templates/dcim/interface.html:222
#: netbox/templates/dcim/interface.html:235
#: netbox/templates/dcim/inventoryitem.html:28
#: netbox/templates/dcim/inventoryitemrole.html:18
#: netbox/templates/dcim/location.html:29
@@ -1862,7 +1862,7 @@ msgstr ""
#: netbox/circuits/tables/virtual_circuits.py:42
#: netbox/templates/circuits/circuit.html:26
#: netbox/templates/circuits/virtualcircuit.html:35
#: netbox/templates/dcim/interface.html:174
#: netbox/templates/dcim/interface.html:187
msgid "Circuit ID"
msgstr ""
@@ -1940,7 +1940,7 @@ msgstr ""
#: netbox/templates/circuits/providernetwork.html:17
#: netbox/templates/circuits/virtualcircuit.html:27
#: netbox/templates/circuits/virtualcircuittermination.html:30
#: netbox/templates/dcim/interface.html:170
#: netbox/templates/dcim/interface.html:183
msgid "Provider Network"
msgstr ""
@@ -2010,7 +2010,7 @@ msgstr ""
#: netbox/templates/dcim/devicebay.html:48
#: netbox/templates/dcim/frontport.html:20
#: netbox/templates/dcim/interface.html:30
#: netbox/templates/dcim/interface.html:218
#: netbox/templates/dcim/interface.html:231
#: netbox/templates/dcim/inventoryitem.html:20
#: netbox/templates/dcim/module.html:57 netbox/templates/dcim/modulebay.html:20
#: netbox/templates/dcim/poweroutlet.html:20
@@ -2212,7 +2212,7 @@ msgstr ""
#: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:53
#: netbox/templates/core/plugin.html:88
#: netbox/templates/dcim/interface.html:273
#: netbox/templates/dcim/interface.html:286
msgid "Local"
msgstr ""
@@ -3072,16 +3072,16 @@ msgstr ""
msgid "Plugin {name} not found"
msgstr ""
#: netbox/dcim/api/serializers_/device_components.py:263
#: netbox/dcim/api/serializers_/device_components.py:264
msgid "Interface mode does not support q-in-q service vlan"
msgstr ""
#: netbox/dcim/api/serializers_/device_components.py:270
#: netbox/dcim/api/serializers_/device_components.py:271
msgid "Interface mode does not support untagged vlan"
msgstr ""
#: netbox/dcim/api/serializers_/device_components.py:275
#: netbox/dcim/api/serializers_/device_components.py:280
#: netbox/dcim/api/serializers_/device_components.py:276
#: netbox/dcim/api/serializers_/device_components.py:281
msgid "Interface mode does not support tagged vlans"
msgstr ""
@@ -3205,7 +3205,7 @@ msgstr ""
#: netbox/ipam/tables/ip.py:336 netbox/ipam/tables/services.py:45
#: netbox/templates/dcim/devicerole.html:34
#: netbox/templates/dcim/interface.html:108
#: netbox/templates/dcim/interface.html:366
#: netbox/templates/dcim/interface.html:379
#: netbox/templates/dcim/location.html:41
#: netbox/templates/dcim/platform.html:37 netbox/templates/dcim/region.html:37
#: netbox/templates/dcim/sitegroup.html:37
@@ -3334,7 +3334,7 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:1635 netbox/dcim/forms/model_forms.py:1130
#: netbox/dcim/forms/model_forms.py:1583 netbox/netbox/navigation/menu.py:147
#: netbox/netbox/navigation/menu.py:151
#: netbox/templates/dcim/interface.html:267
#: netbox/templates/dcim/interface.html:280
msgid "Wireless"
msgstr ""
@@ -4017,7 +4017,7 @@ msgstr ""
#: netbox/ipam/models/ip.py:748 netbox/ipam/models/vrfs.py:61
#: netbox/ipam/tables/ip.py:189 netbox/ipam/tables/ip.py:262
#: netbox/ipam/tables/ip.py:318 netbox/ipam/tables/ip.py:418
#: netbox/templates/dcim/interface.html:152
#: netbox/templates/dcim/interface.html:165
#: netbox/templates/ipam/ipaddress.html:18
#: netbox/templates/ipam/iprange.html:47 netbox/templates/ipam/prefix.html:19
#: netbox/templates/ipam/vrf.html:7 netbox/templates/ipam/vrf.html:13
@@ -4102,7 +4102,7 @@ msgid "LAG interface (ID)"
msgstr ""
#: netbox/dcim/filtersets.py:2008 netbox/dcim/tables/devices.py:635
#: netbox/dcim/tables/devices.py:1164 netbox/templates/dcim/interface.html:131
#: netbox/dcim/tables/devices.py:1164 netbox/templates/dcim/interface.html:144
#: netbox/templates/dcim/macaddress.html:11
#: netbox/templates/dcim/macaddress.html:14
#: netbox/templates/virtualization/vminterface.html:79
@@ -4721,7 +4721,7 @@ msgid "Module"
msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1519 netbox/dcim/tables/devices.py:728
#: netbox/templates/dcim/interface.html:116
#: netbox/templates/dcim/interface.html:129
msgid "LAG"
msgstr ""
@@ -4799,7 +4799,7 @@ msgstr ""
#: netbox/dcim/forms/bulk_edit.py:1628 netbox/dcim/forms/model_forms.py:1507
#: netbox/dcim/tables/devices.py:670 netbox/netbox/navigation/menu.py:153
#: netbox/templates/dcim/interface.html:337
#: netbox/templates/dcim/interface.html:350
#: netbox/wireless/tables/wirelesslan.py:28
msgid "Wireless LANs"
msgstr ""
@@ -4808,7 +4808,7 @@ msgstr ""
#: netbox/dcim/forms/model_forms.py:1573 netbox/ipam/forms/bulk_edit.py:269
#: netbox/ipam/forms/bulk_edit.py:367 netbox/ipam/forms/filtersets.py:177
#: netbox/netbox/navigation/menu.py:109
#: netbox/templates/dcim/interface.html:128
#: netbox/templates/dcim/interface.html:141
#: netbox/templates/ipam/prefix.html:91
#: netbox/templates/virtualization/vminterface.html:76
#: netbox/virtualization/forms/filtersets.py:205
@@ -5563,7 +5563,7 @@ msgstr ""
#: netbox/templates/dcim/consoleport.html:55
#: netbox/templates/dcim/consoleserverport.html:55
#: netbox/templates/dcim/frontport.html:69
#: netbox/templates/dcim/interface.html:197
#: netbox/templates/dcim/interface.html:210
#: netbox/templates/dcim/powerfeed.html:110
#: netbox/templates/dcim/poweroutlet.html:73
#: netbox/templates/dcim/powerport.html:59
@@ -5584,7 +5584,7 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:1570 netbox/dcim/forms/model_forms.py:1561
#: netbox/dcim/models/device_components.py:735
#: netbox/templates/dcim/interface.html:142
#: netbox/templates/dcim/interface.html:155
msgid "WWN"
msgstr ""
@@ -5798,7 +5798,7 @@ msgstr ""
#: netbox/templates/dcim/consoleserverport.html:76
#: netbox/templates/dcim/frontport.html:17
#: netbox/templates/dcim/frontport.html:115
#: netbox/templates/dcim/interface.html:244
#: netbox/templates/dcim/interface.html:257
#: netbox/templates/dcim/rearport.html:105
msgid "Front Port"
msgstr ""
@@ -5810,7 +5810,7 @@ msgstr ""
#: netbox/templates/dcim/consoleserverport.html:79
#: netbox/templates/dcim/frontport.html:50
#: netbox/templates/dcim/frontport.html:118
#: netbox/templates/dcim/interface.html:247
#: netbox/templates/dcim/interface.html:260
#: netbox/templates/dcim/rearport.html:17
#: netbox/templates/dcim/rearport.html:108
msgid "Rear Port"
@@ -7730,7 +7730,7 @@ msgstr ""
#: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:689
#: netbox/ipam/views.py:790 netbox/netbox/navigation/menu.py:165
#: netbox/netbox/navigation/menu.py:167
#: netbox/templates/dcim/interface.html:396
#: netbox/templates/dcim/interface.html:409
#: netbox/templates/ipam/ipaddress_bulk_add.html:15
#: netbox/templates/ipam/service.html:42
#: netbox/templates/virtualization/vminterface.html:107
@@ -7763,7 +7763,7 @@ msgstr ""
msgid "VDCs"
msgstr ""
#: netbox/dcim/tables/devices.py:681 netbox/templates/dcim/interface.html:163
#: netbox/dcim/tables/devices.py:681 netbox/templates/dcim/interface.html:176
msgid "Virtual Circuit"
msgstr ""
@@ -8008,31 +8008,31 @@ msgstr ""
msgid "Virtual Machines"
msgstr ""
#: netbox/dcim/views.py:3238
#: netbox/dcim/views.py:3239
#, python-brace-format
msgid "Installed device {device} in bay {device_bay}."
msgstr ""
#: netbox/dcim/views.py:3279
#: netbox/dcim/views.py:3280
#, python-brace-format
msgid "Removed device {device} from bay {device_bay}."
msgstr ""
#: netbox/dcim/views.py:3392 netbox/ipam/tables/ip.py:181
#: netbox/dcim/views.py:3393 netbox/ipam/tables/ip.py:181
msgid "Children"
msgstr ""
#: netbox/dcim/views.py:3865
#: netbox/dcim/views.py:3866
#, python-brace-format
msgid "Added member <a href=\"{url}\">{device}</a>"
msgstr ""
#: netbox/dcim/views.py:3910
#: netbox/dcim/views.py:3911
#, python-brace-format
msgid "Unable to remove master device {device} from the virtual chassis."
msgstr ""
#: netbox/dcim/views.py:3921
#: netbox/dcim/views.py:3922
#, python-brace-format
msgid "Removed {device} from virtual chassis {chassis}"
msgstr ""
@@ -9394,7 +9394,12 @@ msgstr ""
msgid "Must define base or extra choices."
msgstr ""
#: netbox/extras/models/customfields.py:903
#: netbox/extras/models/customfields.py:888
#, python-brace-format
msgid "Duplicate value '{value}' found in extra choices."
msgstr ""
#: netbox/extras/models/customfields.py:913
#, python-brace-format
msgid ""
"Cannot remove choice {choice} as there are {model} objects which reference "
@@ -11869,51 +11874,46 @@ msgstr ""
msgid "{class_name} must specify a model class."
msgstr ""
#: netbox/netbox/models/features.py:294
#, python-brace-format
msgid "Unknown field name '{name}' in custom field data."
msgstr ""
#: netbox/netbox/models/features.py:300
#: netbox/netbox/models/features.py:301
#, python-brace-format
msgid "Invalid value for custom field '{name}': {error}"
msgstr ""
#: netbox/netbox/models/features.py:309
#: netbox/netbox/models/features.py:310
#, python-brace-format
msgid "Custom field '{name}' must have a unique value."
msgstr ""
#: netbox/netbox/models/features.py:316
#: netbox/netbox/models/features.py:317
#, python-brace-format
msgid "Missing required custom field '{name}'."
msgstr ""
#: netbox/netbox/models/features.py:506
#: netbox/netbox/models/features.py:507
msgid "Remote data source"
msgstr ""
#: netbox/netbox/models/features.py:516
#: netbox/netbox/models/features.py:517
msgid "data path"
msgstr ""
#: netbox/netbox/models/features.py:520
#: netbox/netbox/models/features.py:521
msgid "Path to remote file (relative to data source root)"
msgstr ""
#: netbox/netbox/models/features.py:523
#: netbox/netbox/models/features.py:524
msgid "auto sync enabled"
msgstr ""
#: netbox/netbox/models/features.py:525
#: netbox/netbox/models/features.py:526
msgid "Enable automatic synchronization of data when the data file is updated"
msgstr ""
#: netbox/netbox/models/features.py:528
#: netbox/netbox/models/features.py:529
msgid "date synced"
msgstr ""
#: netbox/netbox/models/features.py:622
#: netbox/netbox/models/features.py:623
#, python-brace-format
msgid "{class_name} must implement a sync_data() method."
msgstr ""
@@ -11998,13 +11998,13 @@ msgid "Inventory Item Roles"
msgstr ""
#: netbox/netbox/navigation/menu.py:111
#: netbox/templates/dcim/interface.html:413
#: netbox/templates/dcim/interface.html:426
#: netbox/templates/virtualization/vminterface.html:124
msgid "MAC Addresses"
msgstr ""
#: netbox/netbox/navigation/menu.py:118 netbox/netbox/navigation/menu.py:122
#: netbox/templates/dcim/interface.html:182
#: netbox/templates/dcim/interface.html:195
msgid "Connections"
msgstr ""
@@ -12760,18 +12760,22 @@ msgid "None installed"
msgstr ""
#: netbox/templates/500.html:39
msgid "The request which yielded the above error is shown below:"
msgstr ""
#: netbox/templates/500.html:45
msgid "If further assistance is required, please post to the"
msgstr ""
#: netbox/templates/500.html:39
#: netbox/templates/500.html:45
msgid "NetBox discussion forum"
msgstr ""
#: netbox/templates/500.html:39
#: netbox/templates/500.html:45
msgid "on GitHub"
msgstr ""
#: netbox/templates/500.html:42 netbox/templates/base/40x.html:17
#: netbox/templates/500.html:48 netbox/templates/base/40x.html:17
msgid "Home Page"
msgstr ""
@@ -12908,7 +12912,7 @@ msgstr ""
#: netbox/templates/core/objectchange.html:148
#: netbox/templates/dcim/devicebay.html:59
#: netbox/templates/dcim/inc/panels/inventory_items.html:45
#: netbox/templates/dcim/interface.html:353
#: netbox/templates/dcim/interface.html:366
#: netbox/templates/dcim/modulebay.html:80
#: netbox/templates/dcim/moduletype.html:90
#: netbox/templates/extras/configcontext.html:46
@@ -13072,7 +13076,7 @@ msgstr ""
#: netbox/templates/dcim/inc/cable_termination.html:48
#: netbox/templates/dcim/inc/cable_termination.html:66
#: netbox/templates/dcim/inc/connection_endpoints.html:7
#: netbox/templates/dcim/interface.html:211
#: netbox/templates/dcim/interface.html:224
#: netbox/templates/dcim/rearport.html:76
msgid "Trace"
msgstr ""
@@ -13095,8 +13099,8 @@ msgstr ""
#: netbox/templates/dcim/consoleport.html:69
#: netbox/templates/dcim/consoleserverport.html:69
#: netbox/templates/dcim/frontport.html:102
#: netbox/templates/dcim/interface.html:237
#: netbox/templates/dcim/interface.html:257
#: netbox/templates/dcim/interface.html:250
#: netbox/templates/dcim/interface.html:270
#: netbox/templates/dcim/powerfeed.html:123
#: netbox/templates/dcim/poweroutlet.html:85
#: netbox/templates/dcim/poweroutlet.html:86
@@ -13635,7 +13639,7 @@ msgstr ""
#: netbox/templates/dcim/consoleport.html:65
#: netbox/templates/dcim/consoleserverport.html:65
#: netbox/templates/dcim/frontport.html:98
#: netbox/templates/dcim/interface.html:233
#: netbox/templates/dcim/interface.html:246
#: netbox/templates/dcim/poweroutlet.html:83
#: netbox/templates/dcim/powerport.html:69
msgid "Not Connected"
@@ -13837,7 +13841,7 @@ msgid "Rear Port Position"
msgstr ""
#: netbox/templates/dcim/frontport.html:72
#: netbox/templates/dcim/interface.html:201
#: netbox/templates/dcim/interface.html:214
#: netbox/templates/dcim/poweroutlet.html:77
#: netbox/templates/dcim/powerport.html:63
#: netbox/templates/dcim/rearport.html:68
@@ -13945,38 +13949,42 @@ msgstr ""
msgid "PoE Type"
msgstr ""
#: netbox/templates/dcim/interface.html:156
#: netbox/templates/dcim/interface.html:116
msgid "Bridged Interfaces"
msgstr ""
#: netbox/templates/dcim/interface.html:169
#: netbox/templates/virtualization/vminterface.html:94
msgid "VLAN Translation"
msgstr ""
#: netbox/templates/dcim/interface.html:208
#: netbox/templates/dcim/interface.html:221
msgid "Wireless Link"
msgstr ""
#: netbox/templates/dcim/interface.html:287
#: netbox/templates/dcim/interface.html:300
#: netbox/templates/wireless/inc/wirelesslink_interface.html:26
msgid "Channel"
msgstr ""
#: netbox/templates/dcim/interface.html:296
#: netbox/templates/dcim/interface.html:309
#: netbox/templates/wireless/inc/wirelesslink_interface.html:32
msgid "Channel Frequency"
msgstr ""
#: netbox/templates/dcim/interface.html:299
#: netbox/templates/dcim/interface.html:307
#: netbox/templates/dcim/interface.html:318
#: netbox/templates/dcim/interface.html:326
#: netbox/templates/dcim/interface.html:312
#: netbox/templates/dcim/interface.html:320
#: netbox/templates/dcim/interface.html:331
#: netbox/templates/dcim/interface.html:339
msgid "MHz"
msgstr ""
#: netbox/templates/dcim/interface.html:315
#: netbox/templates/dcim/interface.html:328
#: netbox/templates/wireless/inc/wirelesslink_interface.html:42
msgid "Channel Width"
msgstr ""
#: netbox/templates/dcim/interface.html:342
#: netbox/templates/dcim/interface.html:355
#: netbox/templates/wireless/wirelesslan.html:14
#: netbox/templates/wireless/wirelesslink.html:21
#: netbox/wireless/forms/bulk_edit.py:63 netbox/wireless/forms/bulk_edit.py:106
@@ -13986,15 +13994,15 @@ msgstr ""
msgid "SSID"
msgstr ""
#: netbox/templates/dcim/interface.html:362
#: netbox/templates/dcim/interface.html:375
msgid "LAG Members"
msgstr ""
#: netbox/templates/dcim/interface.html:380
#: netbox/templates/dcim/interface.html:393
msgid "No member interfaces"
msgstr ""
#: netbox/templates/dcim/interface.html:400
#: netbox/templates/dcim/interface.html:413
#: netbox/templates/ipam/fhrpgroup.html:74
#: netbox/templates/ipam/iprange/ip_addresses.html:7
#: netbox/templates/ipam/prefix/ip_addresses.html:7
@@ -14002,7 +14010,7 @@ msgstr ""
msgid "Add IP Address"
msgstr ""
#: netbox/templates/dcim/interface.html:417
#: netbox/templates/dcim/interface.html:430
#: netbox/templates/virtualization/vminterface.html:129
msgid "Add MAC Address"
msgstr ""

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
[project]
name = "netbox"
version = "4.4.9"
version = "4.4.10"
requires-python = ">=3.10"
description = "The premier source of truth powering network automation."
readme = "README.md"

View File

@@ -10,14 +10,14 @@ django-pglocks==1.0.4
django-prometheus==2.4.1
django-redis==6.0.0
django-rich==2.2.0
django-rq==3.2.1
django-rq==3.2.2
django-storages==1.14.6
django-tables2==2.8.0
django-taggit==6.1.0
django-timezone-field==7.2.1
djangorestframework==3.16.1
drf-spectacular==0.29.0
drf-spectacular-sidecar==2025.12.1
drf-spectacular-sidecar==2026.1.1
feedparser==6.0.12
gunicorn==23.0.0
Jinja2==3.1.6
@@ -28,7 +28,7 @@ mkdocstrings==1.0.0
mkdocstrings-python==2.0.1
netaddr==1.3.0
nh3==0.3.2
Pillow==12.0.0
Pillow==12.1.0
psycopg[c,pool]==3.3.2
PyYAML==6.0.3
requests==2.32.5
@@ -36,8 +36,8 @@ rq==2.6.1
social-auth-app-django==5.7.0
social-auth-core==4.8.3
sorl-thumbnail==12.11.0
strawberry-graphql==0.287.3
strawberry-graphql-django==0.70.1
strawberry-graphql==0.288.2
strawberry-graphql-django==0.73.0
svgwrite==1.4.3
tablib==3.9.0
tzdata==2025.3