Skip to content

Commit 37a9d03

Browse files
committed
Merge branch 'main' into feature
2 parents a91af99 + a69bbcf commit 37a9d03

File tree

81 files changed

+5741
-5165
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+5741
-5165
lines changed

.github/ISSUE_TEMPLATE/01-feature_request.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ body:
1515
attributes:
1616
label: NetBox version
1717
description: What version of NetBox are you currently running?
18-
placeholder: v4.4.2
18+
placeholder: v4.4.3
1919
validations:
2020
required: true
2121
- type: dropdown

.github/ISSUE_TEMPLATE/02-bug_report.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ body:
2727
attributes:
2828
label: NetBox Version
2929
description: What version of NetBox are you currently running?
30-
placeholder: v4.4.2
30+
placeholder: v4.4.3
3131
validations:
3232
required: true
3333
- type: dropdown

base_requirements.txt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ django-cors-headers
1212

1313
# Runtime UI tool for debugging Django
1414
# https://github.com/jazzband/django-debug-toolbar/blob/main/docs/changes.rst
15-
# django-debug-toolbar v6.0.0 raises "Attribute Error at /: 'function' object has no attribute 'set'"
16-
# see https://github.com/netbox-community/netbox/issues/19974
17-
django-debug-toolbar==5.2.0
15+
django-debug-toolbar
1816

1917
# Library for writing reusable URL query filters
2018
# https://github.com/carltongibson/django-filter/blob/main/CHANGES.rst
@@ -71,7 +69,8 @@ django-timezone-field
7169

7270
# A REST API framework for Django projects
7371
# https://www.django-rest-framework.org/community/release-notes/
74-
djangorestframework
72+
# TODO: Re-evaluate the monkey-patch of get_unique_validators() before upgrading
73+
djangorestframework==3.16.1
7574

7675
# Sane and flexible OpenAPI 3 schema generation for Django REST framework.
7776
# https://github.com/tfranzel/drf-spectacular/blob/master/CHANGELOG.rst

contrib/openapi.json

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"openapi": "3.0.3",
33
"info": {
44
"title": "NetBox REST API",
5-
"version": "4.4.2",
5+
"version": "4.4.3",
66
"license": {
77
"name": "Apache v2 License"
88
}
@@ -214738,24 +214738,26 @@
214738214738
"IntegerRange": {
214739214739
"type": "array",
214740214740
"items": {
214741-
"type": "array",
214742-
"items": {
214743-
"type": "integer"
214744-
},
214745-
"minItems": 2,
214746-
"maxItems": 2
214747-
}
214741+
"type": "integer"
214742+
},
214743+
"minItems": 2,
214744+
"maxItems": 2,
214745+
"example": [
214746+
10,
214747+
20
214748+
]
214748214749
},
214749214750
"IntegerRangeRequest": {
214750214751
"type": "array",
214751214752
"items": {
214752-
"type": "array",
214753-
"items": {
214754-
"type": "integer"
214755-
},
214756-
"minItems": 2,
214757-
"maxItems": 2
214758-
}
214753+
"type": "integer"
214754+
},
214755+
"minItems": 2,
214756+
"maxItems": 2,
214757+
"example": [
214758+
10,
214759+
20
214760+
]
214759214761
},
214760214762
"Interface": {
214761214763
"type": "object",

docs/plugins/development/filtersets.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Filters & Filter Sets
22

3-
Filter sets define the mechanisms available for filtering or searching through a set of objects in NetBox. For instance, sites can be filtered by their parent region or group, status, facility ID, and so on. The same filter set is used consistently for a model whether the request is made via the UI or REST API. (Note that the GraphQL API uses a separate filter class.) NetBox employs the [django-filters2](https://django-tables2.readthedocs.io/en/latest/) library to define filter sets.
3+
Filter sets define the mechanisms available for filtering or searching through a set of objects in NetBox. For instance, sites can be filtered by their parent region or group, status, facility ID, and so on. The same filter set is used consistently for a model whether the request is made via the UI or REST API. (Note that the GraphQL API uses a separate filter class.) NetBox employs the [django-filter](https://django-filter.readthedocs.io/en/stable/) library to define filter sets.
44

55
## FilterSet Classes
66

docs/release-notes/version-4.4.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,32 @@
11
# NetBox v4.4
22

3+
## v4.4.3 (2025-10-14)
4+
5+
### Enhancements
6+
7+
* [#20426](https://github.com/netbox-community/netbox/issues/20426) - Add a copy-to-clipboard button for custom script output
8+
* [#20516](https://github.com/netbox-community/netbox/issues/20516) - Improve rendering of VLAN ID ranges in VLAN group tables
9+
10+
### Bug Fixes
11+
12+
* [#19302](https://github.com/netbox-community/netbox/issues/19302) - Fix uniqueness validation in REST API for nullable fields
13+
* [#19615](https://github.com/netbox-community/netbox/issues/19615) - Fix support for static file parameters in templates when external storage is in use
14+
* [#19818](https://github.com/netbox-community/netbox/issues/19818) - Hide primary IP assignment fields when creating a new virtual machine in the UI
15+
* [#19825](https://github.com/netbox-community/netbox/issues/19825) - Prevent cache for config revisions from being erroneously overwritten when debugging is enabled
16+
* [#20140](https://github.com/netbox-community/netbox/issues/20140) - Changing a site's region or group should update any associated circuit terminations
17+
* [#20156](https://github.com/netbox-community/netbox/issues/20156) - Fix display of rack elevation labels
18+
* [#20290](https://github.com/netbox-community/netbox/issues/20290) - Fix migration error when upgrading to NetBox v4.4 from releases earlier than v4.3
19+
* [#20471](https://github.com/netbox-community/netbox/issues/20471) - Saving an unmodified VLAN group should not generate a change record
20+
* [#20475](https://github.com/netbox-community/netbox/issues/20475) - Collapse singleton VLAN IDs in VLAN group display
21+
* [#20494](https://github.com/netbox-community/netbox/issues/20494) - Correct OpenAPI schema definition for `IntegerRangeSerializer`
22+
* [#20496](https://github.com/netbox-community/netbox/issues/20496) - REST API should always honor `MAX_PAGE_SIZE` value
23+
* [#20497](https://github.com/netbox-community/netbox/issues/20497) - Fix filtering of VLAN groups by VLAN ID range in GraphQL API
24+
* [#20507](https://github.com/netbox-community/netbox/issues/20507) - Fix support for fetching ASN contacts via GraphQL API
25+
* [#20523](https://github.com/netbox-community/netbox/issues/20523) - Hide password change form for users authenticated via SSO
26+
* [#20542](https://github.com/netbox-community/netbox/issues/20542) - Fix the creation of MAC addresses using the "quick add" form
27+
28+
---
29+
330
## v4.4.2 (2025-09-30)
431

532
### Enhancements

netbox/circuits/apps.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from django.apps import AppConfig
22

3+
from netbox import denormalized
4+
35

46
class CircuitsConfig(AppConfig):
57
name = "circuits"
@@ -8,6 +10,16 @@ class CircuitsConfig(AppConfig):
810
def ready(self):
911
from netbox.models.features import register_models
1012
from . import signals, search # noqa: F401
13+
from .models import CircuitTermination
1114

1215
# Register models
1316
register_models(*self.get_models())
17+
18+
denormalized.register(CircuitTermination, '_site', {
19+
'_region': 'region',
20+
'_site_group': 'group',
21+
})
22+
23+
denormalized.register(CircuitTermination, '_location', {
24+
'_site': 'site',
25+
})

netbox/core/api/schema.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -282,18 +282,18 @@ def map_serializer_field(self, auto_schema, direction):
282282

283283
class FixIntegerRangeSerializerSchema(OpenApiSerializerExtension):
284284
target_class = 'netbox.api.fields.IntegerRangeSerializer'
285+
match_subclasses = True
285286

286287
def map_serializer(self, auto_schema: 'AutoSchema', direction: Direction) -> _SchemaType:
288+
# One range = two integers; many=True will wrap this in an outer array
287289
return {
288290
'type': 'array',
289291
'items': {
290-
'type': 'array',
291-
'items': {
292-
'type': 'integer',
293-
},
294-
'minItems': 2,
295-
'maxItems': 2,
292+
'type': 'integer',
296293
},
294+
'minItems': 2,
295+
'maxItems': 2,
296+
'example': [10, 20],
297297
}
298298

299299

netbox/core/graphql/mixins.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
import strawberry
44
import strawberry_django
55
from django.contrib.contenttypes.models import ContentType
6+
from strawberry.types import Info
67

78
from core.models import ObjectChange
89

910
if TYPE_CHECKING:
10-
from core.graphql.types import DataFileType, DataSourceType
11-
from netbox.core.graphql.types import ObjectChangeType
11+
from core.graphql.types import DataFileType, DataSourceType, ObjectChangeType
1212

1313
__all__ = (
1414
'ChangelogMixin',
@@ -20,7 +20,7 @@
2020
class ChangelogMixin:
2121

2222
@strawberry_django.field
23-
def changelog(self, info) -> List[Annotated["ObjectChangeType", strawberry.lazy('.types')]]: # noqa: F821
23+
def changelog(self, info: Info) -> List[Annotated['ObjectChangeType', strawberry.lazy('.types')]]: # noqa: F821
2424
content_type = ContentType.objects.get_for_model(self)
2525
object_changes = ObjectChange.objects.filter(
2626
changed_object_type=content_type,
@@ -31,5 +31,5 @@ def changelog(self, info) -> List[Annotated["ObjectChangeType", strawberry.lazy(
3131

3232
@strawberry.type
3333
class SyncedDataMixin:
34-
data_source: Annotated["DataSourceType", strawberry.lazy('core.graphql.types')] | None
35-
data_file: Annotated["DataFileType", strawberry.lazy('core.graphql.types')] | None
34+
data_source: Annotated['DataSourceType', strawberry.lazy('core.graphql.types')] | None
35+
data_file: Annotated['DataFileType', strawberry.lazy('core.graphql.types')] | None
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Generated by Django 5.2.5 on 2025-09-09 16:48
2+
3+
from django.db import migrations, models
4+
5+
6+
def get_active(apps, schema_editor):
7+
from django.core.cache import cache
8+
ConfigRevision = apps.get_model('core', 'ConfigRevision')
9+
version = None
10+
revision = None
11+
12+
# Try and get the latest version from cache
13+
try:
14+
version = cache.get('config_version')
15+
except Exception:
16+
pass
17+
18+
# If there is a version in cache, attempt to set revision to the current version from cache
19+
# If the version in cache does not exist or there is no version, try the lastest revision in the database
20+
if not version or (version and not (revision := ConfigRevision.objects.filter(pk=version).first())):
21+
revision = ConfigRevision.objects.order_by('-created').first()
22+
23+
# If there is a revision set, set the active revision
24+
if revision:
25+
revision.active = True
26+
revision.save()
27+
28+
29+
class Migration(migrations.Migration):
30+
31+
dependencies = [
32+
('core', '0018_concrete_objecttype'),
33+
]
34+
35+
operations = [
36+
migrations.AddField(
37+
model_name='configrevision',
38+
name='active',
39+
field=models.BooleanField(default=False),
40+
),
41+
migrations.RunPython(code=get_active, reverse_code=migrations.RunPython.noop),
42+
migrations.AddConstraint(
43+
model_name='configrevision',
44+
constraint=models.UniqueConstraint(
45+
condition=models.Q(('active', True)), fields=('active',), name='unique_active_config_revision'
46+
),
47+
),
48+
]

0 commit comments

Comments
 (0)