Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v3.5.5 #13111

Merged
merged 37 commits into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
70c2b35
PRVB
jeremystretch Jun 20, 2023
13315f3
fixes device type and module type tag import #12949
abhi1693 Jun 23, 2023
7f96c7f
fixes most schema warnings #12257
abhi1693 Jun 23, 2023
49af70a
fixes choice field schema for response #12960
abhi1693 Jun 23, 2023
79c8219
fixes device interface serializer #12533
abhi1693 Jun 23, 2023
c83b249
fix db maintenance mode exception #12966
abhi1693 Jun 23, 2023
27e850a
fix ip address assignment #12953
abhi1693 Jun 23, 2023
882f291
Fixes #12975: Correct URL for VirtualDeviceContext API serializer
jeremystretch Jun 23, 2023
32fe9fe
Changelog for #12533, #12960, #12963, #12966, #12975, #12989
jeremystretch Jun 23, 2023
d131d9b
Correct changelog for #12953
jeremystretch Jun 23, 2023
74d9fe1
Fixes #12961: Set correct return_url for object contacts tabs
jeremystretch Jun 23, 2023
290ffd4
Fixes #12977: Fix URL parameters for object count dashboard widgets (…
jeremystretch Jun 26, 2023
f1858a7
Fixes #13011: Allow comma in custom links
v0tti Jun 27, 2023
16d5107
Add QSFP-DD (100GE) interface type
pobradovic08 Jun 26, 2023
c99e565
fix remote auth backend check
rmanyari Jun 26, 2023
34d3237
Fix #12983 bulk edit of M2M fields when nothing is selected
Urth Jun 26, 2023
6b01b1d
Changelog for #12849, #12945, #12961, #12977, #12983, #13011
jeremystretch Jun 27, 2023
b13f9d2
Fix Repography charts
jeremystretch Jun 27, 2023
0a60a3f
Add OneMind Services as a sponsor
jeremystretch Jun 29, 2023
183c7de
adds contact accessor fields on assignment table #12955
abhi1693 Jun 29, 2023
dd6d9bf
List multiple devices in Terminations (#13030)
pobradovic08 Jun 29, 2023
3754e00
12809 document not to use underscores in model names
arthanson Jun 27, 2023
f69d99e
Fixes #12760 - Adds Vary header to cause cache to be keyed based on U…
DanSheps Jun 27, 2023
3307bd2
Fixes syntax error on reports (#12997)
abhi1693 Jun 29, 2023
63ba9fb
Fixes #11335: Default manager for ObjectChange should filter by insta…
jeremystretch Jul 5, 2023
07ae7c8
Changelog for #11335, #12760, #12842, #12951, #12955
jeremystretch Jul 5, 2023
4355ee6
12092 allow setnull for bulk edit power port maximum and allocated draw
arthanson Jul 6, 2023
5f09227
Fixes #13047: Add annotate_asn_count() to ASNRange manager
jeremystretch Jun 29, 2023
860be78
Fix #12579 create cable and add another error (#13007)
netopsab Jul 6, 2023
16ee42a
fixes prechange snapshot #12617
abhi1693 Jun 23, 2023
ffe4558
fixes search for vdc #13100
abhi1693 Jul 6, 2023
8143c6e
adds object change for contact assignment #13065
abhi1693 Jul 6, 2023
62bdb90
Adds copy content button (#12584)
abhi1693 Jul 6, 2023
7419a8e
Closes #11738: Annotate utilization on VLAN groups (#13108)
jeremystretch Jul 6, 2023
ecb4a08
Change log for #11738, #12499, #12579, #12617, #13047, #13065, #13092…
jeremystretch Jul 6, 2023
74fb707
adds config_template to device serializer #13056
abhi1693 Jul 6, 2023
53a75a3
Release v3.5.5
jeremystretch Jul 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
placeholder: v3.5.4
placeholder: v3.5.5
validations:
required: true
- type: dropdown
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
placeholder: v3.5.4
placeholder: v3.5.5
validations:
required: true
- type: dropdown
Expand Down
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ as the cornerstone for network automation in thousands of organizations.
## Project Stats

<div align="center">
<a href="https://github.com/netbox-community/netbox/commits"><img src="https://images.repography.com/29023055/netbox-community/netbox/recent-activity/31db894eee74b8a5475e3af307a81b6c_timeline.svg" alt="Timeline graph"></a>
<a href="https://github.com/netbox-community/netbox/issues"><img src="https://images.repography.com/29023055/netbox-community/netbox/recent-activity/31db894eee74b8a5475e3af307a81b6c_issues.svg" alt="Issues graph"></a>
<a href="https://github.com/netbox-community/netbox/pulls"><img src="https://images.repography.com/29023055/netbox-community/netbox/recent-activity/31db894eee74b8a5475e3af307a81b6c_prs.svg" alt="Pull requests graph"></a>
<a href="https://github.com/netbox-community/netbox/graphs/contributors"><img src="https://images.repography.com/29023055/netbox-community/netbox/recent-activity/31db894eee74b8a5475e3af307a81b6c_users.svg" alt="Top contributors"></a>
<a href="https://github.com/netbox-community/netbox/commits"><img src="https://images.repography.com/29023055/netbox-community/netbox/recent-activity/whQtEr_TGD9PhW1BPlhlEQ5jnrgQ0KJpm-LlGtpoGO0/3Kx_iWUSBRJ5-AI4QwJEJWrUDEz3KrX2lvh8aYE0WXY_timeline.svg" alt="Timeline graph"></a>
<a href="https://github.com/netbox-community/netbox/issues"><img src="https://images.repography.com/29023055/netbox-community/netbox/recent-activity/whQtEr_TGD9PhW1BPlhlEQ5jnrgQ0KJpm-LlGtpoGO0/3Kx_iWUSBRJ5-AI4QwJEJWrUDEz3KrX2lvh8aYE0WXY_issues.svg" alt="Issues graph"></a>
<a href="https://github.com/netbox-community/netbox/pulls"><img src="https://images.repography.com/29023055/netbox-community/netbox/recent-activity/whQtEr_TGD9PhW1BPlhlEQ5jnrgQ0KJpm-LlGtpoGO0/3Kx_iWUSBRJ5-AI4QwJEJWrUDEz3KrX2lvh8aYE0WXY_prs.svg" alt="Pull requests graph"></a>
<a href="https://github.com/netbox-community/netbox/graphs/contributors"><img src="https://images.repography.com/29023055/netbox-community/netbox/recent-activity/whQtEr_TGD9PhW1BPlhlEQ5jnrgQ0KJpm-LlGtpoGO0/3Kx_iWUSBRJ5-AI4QwJEJWrUDEz3KrX2lvh8aYE0WXY_users.svg" alt="Top contributors"></a>
<br />Stats via <a href="https://repography.com">Repography</a>
</div>

Expand All @@ -66,10 +66,12 @@ as the cornerstone for network automation in thousands of organizations.
[![NetBox Labs](https://raw.githubusercontent.com/wiki/netbox-community/netbox/images/sponsors/netbox_labs.png)](https://netboxlabs.com)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
[![DigitalOcean](https://raw.githubusercontent.com/wiki/netbox-community/netbox/images/sponsors/digitalocean.png)](https://try.digitalocean.com/developer-cloud)
<br />
[![Sentry](https://raw.githubusercontent.com/wiki/netbox-community/netbox/images/sponsors/sentry.png)](https://sentry.io)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
[![Sentry](https://raw.githubusercontent.com/wiki/netbox-community/netbox/images/sponsors/sentry.png)](https://sentry.io)
<br />
[![Equinix Metal](https://raw.githubusercontent.com/wiki/netbox-community/netbox/images/sponsors/equinix.png)](https://metal.equinix.com)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
[![OneMind Services](https://raw.githubusercontent.com/wiki/netbox-community/netbox/images/sponsors/onemind_services.png)](https://onemindservices.com)

</div>

Expand Down
3 changes: 3 additions & 0 deletions docs/plugins/development/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ class MyModel(models.Model):

Every model includes by default a numeric primary key. This value is generated automatically by the database, and can be referenced as `pk` or `id`.

!!! note
Model names should adhere to [PEP8](https://www.python.org/dev/peps/pep-0008/#class-names) standards and be CapWords (no underscores). Using underscores in model names will result in problems with permissions.

## Enabling NetBox Features

Plugin models can leverage certain NetBox features by inheriting from NetBox's `NetBoxModel` class. This class extends the plugin model to enable features unique to NetBox, including:
Expand Down
36 changes: 36 additions & 0 deletions docs/release-notes/version-3.5.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,41 @@
# NetBox v3.5

## v3.5.5 (2023-07-06)

### Enhancements

* [#11738](https://github.com/netbox-community/netbox/issues/11738) - Annotate VLAN group utilization
* [#12499](https://github.com/netbox-community/netbox/issues/12499) - Add "copy to clipboard" buttons in UI for IP addresses
* [#12945](https://github.com/netbox-community/netbox/issues/12945) - Add 100GE QSFP-DD interface type
* [#12955](https://github.com/netbox-community/netbox/issues/12955) - Include additional contact details on contact assignments table
* [#13065](https://github.com/netbox-community/netbox/issues/13065) - Associate contact assignments with their objects in the change log

### Bug Fixes

* [#11335](https://github.com/netbox-community/netbox/issues/11335) - Exclude stale content types when retrieving changelog records
* [#12533](https://github.com/netbox-community/netbox/issues/12533) - Fix REST API validation of null values for several interface attributes
* [#12579](https://github.com/netbox-community/netbox/issues/12579) - Fix exception when clicking "create and add another" to add a cable
* [#12617](https://github.com/netbox-community/netbox/issues/12617) - Populate prechange snapshot on parent object when assigning/removing primary IP address
* [#12760](https://github.com/netbox-community/netbox/issues/12760) - Avoid rendering partial HTMX responses when restoring browser tabs
* [#12842](https://github.com/netbox-community/netbox/issues/12842) - Improve handling of exceptions when loading reports
* [#12849](https://github.com/netbox-community/netbox/issues/12849) - Fix LDAP group permissions assignment for API clients
* [#12951](https://github.com/netbox-community/netbox/issues/12951) - Display consistent parent information for each termination under cable view
* [#12953](https://github.com/netbox-community/netbox/issues/12953) - Fix designation of primary IP addresses during interface assignment
* [#12960](https://github.com/netbox-community/netbox/issues/12960) - Fix OpenAPI schema for various choice fields
* [#12961](https://github.com/netbox-community/netbox/issues/12961) - Set correct return URL for object contacts tabs
* [#12966](https://github.com/netbox-community/netbox/issues/12966) - Avoid catching database exceptions when maintenance mode is disabled
* [#12975](https://github.com/netbox-community/netbox/issues/12975) - Correct URL for VirtualDeviceContext API serializer
* [#12977](https://github.com/netbox-community/netbox/issues/12977) - Fix URL parameters for object count dashboard widgets
* [#12983](https://github.com/netbox-community/netbox/issues/12983) - Avoid erroneously clearing many-to-many assignments during bulk edit
* [#12989](https://github.com/netbox-community/netbox/issues/12989) - Fix bulk import of tags for device & module types
* [#13011](https://github.com/netbox-community/netbox/issues/13011) - Do not escape commas when rendering custom links
* [#13047](https://github.com/netbox-community/netbox/issues/13047) - Correct ASN count under ASN ranges list
* [#13056](https://github.com/netbox-community/netbox/issues/13056) - Add `config_template` field to device API serializer
* [#13092](https://github.com/netbox-community/netbox/issues/13092) - Allow nullifying power port max & allocated draw values during bulk edit
* [#13100](https://github.com/netbox-community/netbox/issues/13100) - Fix ValueError exception when searching for virtual device context for non-numeric values

---

## v3.5.4 (2023-06-20)

### Enhancements
Expand Down
12 changes: 9 additions & 3 deletions netbox/core/api/schema.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import re
import typing
from collections import OrderedDict

from drf_spectacular.extensions import OpenApiSerializerFieldExtension
from drf_spectacular.openapi import AutoSchema
Expand Down Expand Up @@ -28,14 +29,19 @@ class ChoiceFieldFix(OpenApiSerializerFieldExtension):
target_class = 'netbox.api.fields.ChoiceField'

def map_serializer_field(self, auto_schema, direction):
build_cf = build_choice_field(self.target)

if direction == 'request':
return build_choice_field(self.target)
return build_cf

elif direction == "response":
value = build_cf
label = {**build_basic_type(OpenApiTypes.STR), "enum": list(OrderedDict.fromkeys(self.target.choices.values()))}

return build_object_type(
properties={
"value": build_basic_type(OpenApiTypes.STR),
"label": build_basic_type(OpenApiTypes.STR),
"value": value,
"label": label
}
)

Expand Down
18 changes: 10 additions & 8 deletions netbox/dcim/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,8 @@ class Meta(DeviceSerializer.Meta):
'id', 'url', 'display', 'name', 'device_type', 'device_role', 'tenant', 'platform', 'serial', 'asset_tag',
'site', 'location', 'rack', 'position', 'face', 'parent_device', 'status', 'airflow', 'primary_ip',
'primary_ip4', 'primary_ip6', 'cluster', 'virtual_chassis', 'vc_position', 'vc_priority', 'description',
'comments', 'local_context_data', 'tags', 'custom_fields', 'config_context', 'created', 'last_updated',
'comments', 'local_context_data', 'tags', 'custom_fields', 'config_context', 'config_template',
'created', 'last_updated',
]

@extend_schema_field(serializers.JSONField(allow_null=True))
Expand All @@ -707,7 +708,7 @@ def get_config_context(self, obj):


class VirtualDeviceContextSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:device-detail')
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:virtualdevicecontext-detail')
device = NestedDeviceSerializer()
tenant = NestedTenantSerializer(required=False, allow_null=True, default=None)
primary_ip = NestedIPAddressSerializer(read_only=True, allow_null=True)
Expand Down Expand Up @@ -880,12 +881,12 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
parent = NestedInterfaceSerializer(required=False, allow_null=True)
bridge = NestedInterfaceSerializer(required=False, allow_null=True)
lag = NestedInterfaceSerializer(required=False, allow_null=True)
mode = ChoiceField(choices=InterfaceModeChoices, required=False, allow_blank=True, allow_null=True)
mode = ChoiceField(choices=InterfaceModeChoices, required=False, allow_blank=True)
duplex = ChoiceField(choices=InterfaceDuplexChoices, required=False, allow_blank=True, allow_null=True)
rf_role = ChoiceField(choices=WirelessRoleChoices, required=False, allow_blank=True, allow_null=True)
rf_channel = ChoiceField(choices=WirelessChannelChoices, required=False, allow_blank=True, allow_null=True)
poe_mode = ChoiceField(choices=InterfacePoEModeChoices, required=False, allow_blank=True, allow_null=True)
poe_type = ChoiceField(choices=InterfacePoETypeChoices, required=False, allow_blank=True, allow_null=True)
rf_role = ChoiceField(choices=WirelessRoleChoices, required=False, allow_blank=True)
rf_channel = ChoiceField(choices=WirelessChannelChoices, required=False, allow_blank=True)
poe_mode = ChoiceField(choices=InterfacePoEModeChoices, required=False, allow_blank=True)
poe_type = ChoiceField(choices=InterfacePoETypeChoices, required=False, allow_blank=True)
untagged_vlan = NestedVLANSerializer(required=False, allow_null=True)
tagged_vlans = SerializedPKRelatedField(
queryset=VLAN.objects.all(),
Expand All @@ -907,9 +908,10 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
mac_address = serializers.CharField(
required=False,
default=None,
allow_blank=True,
allow_null=True
)
wwn = serializers.CharField(required=False, default=None)
wwn = serializers.CharField(required=False, default=None, allow_blank=True, allow_null=True)

class Meta:
model = Interface
Expand Down
2 changes: 2 additions & 0 deletions netbox/dcim/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,7 @@ class InterfaceTypeChoices(ChoiceSet):
TYPE_100GE_CXP = '100gbase-x-cxp'
TYPE_100GE_CPAK = '100gbase-x-cpak'
TYPE_100GE_QSFP28 = '100gbase-x-qsfp28'
TYPE_100GE_QSFP_DD = '100gbase-x-qsfpdd'
TYPE_200GE_CFP2 = '200gbase-x-cfp2'
TYPE_200GE_QSFP56 = '200gbase-x-qsfp56'
TYPE_200GE_QSFP_DD = '200gbase-x-qsfpdd'
Expand Down Expand Up @@ -959,6 +960,7 @@ class InterfaceTypeChoices(ChoiceSet):
(TYPE_100GE_CXP, 'CXP (100GE)'),
(TYPE_100GE_CPAK, 'Cisco CPAK (100GE)'),
(TYPE_100GE_QSFP28, 'QSFP28 (100GE)'),
(TYPE_100GE_QSFP_DD, 'QSFP-DD (100GE)'),
(TYPE_200GE_QSFP56, 'QSFP56 (200GE)'),
(TYPE_200GE_QSFP_DD, 'QSFP-DD (200GE)'),
(TYPE_400GE_QSFP_DD, 'QSFP-DD (400GE)'),
Expand Down
11 changes: 7 additions & 4 deletions netbox/dcim/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1077,10 +1077,13 @@ class Meta:
def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(
Q(name__icontains=value) |
Q(identifier=value.strip())
).distinct()

qs_filter = Q(name__icontains=value)
try:
qs_filter |= Q(identifier=int(value))
except ValueError:
pass
return queryset.filter(qs_filter).distinct()

def _has_primary_ip(self, queryset, name, value):
params = Q(primary_ip4__isnull=False) | Q(primary_ip6__isnull=False)
Expand Down
2 changes: 1 addition & 1 deletion netbox/dcim/forms/bulk_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1106,7 +1106,7 @@ class PowerPortBulkEditForm(
(None, ('module', 'type', 'label', 'description', 'mark_connected')),
('Power', ('maximum_draw', 'allocated_draw')),
)
nullable_fields = ('module', 'label', 'description')
nullable_fields = ('module', 'label', 'description', 'maximum_draw', 'allocated_draw')


class PowerOutletBulkEditForm(
Expand Down
4 changes: 2 additions & 2 deletions netbox/dcim/forms/bulk_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ class Meta:
model = DeviceType
fields = [
'manufacturer', 'default_platform', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth',
'subdevice_role', 'airflow', 'description', 'weight', 'weight_unit', 'comments',
'subdevice_role', 'airflow', 'description', 'weight', 'weight_unit', 'comments', 'tags',
]


Expand All @@ -327,7 +327,7 @@ class ModuleTypeImportForm(NetBoxModelImportForm):

class Meta:
model = ModuleType
fields = ['manufacturer', 'model', 'part_number', 'description', 'weight', 'weight_unit', 'comments']
fields = ['manufacturer', 'model', 'part_number', 'description', 'weight', 'weight_unit', 'comments', 'tags']


class DeviceRoleImportForm(NetBoxModelImportForm):
Expand Down
13 changes: 13 additions & 0 deletions netbox/dcim/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3131,6 +3131,19 @@ def get_object(self, **kwargs):

return obj

def get_extra_addanother_params(self, request):

params = {
'a_terminations_type': request.GET.get('a_terminations_type'),
'b_terminations_type': request.GET.get('b_terminations_type')
}

for key in request.POST:
if 'device' in key or 'power_panel' in key or 'circuit' in key:
params.update({key: request.POST.get(key)})

return params


@register_model_view(Cable, 'delete')
class CableDeleteView(generic.ObjectDeleteView):
Expand Down
2 changes: 1 addition & 1 deletion netbox/extras/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ class ObjectChangeViewSet(ReadOnlyModelViewSet):
Retrieve a list of recent changes.
"""
metadata_class = ContentTypeMetadata
queryset = ObjectChange.objects.prefetch_related('user')
queryset = ObjectChange.objects.valid_models().prefetch_related('user')
serializer_class = serializers.ObjectChangeSerializer
filterset_class = filtersets.ObjectChangeFilterSet

Expand Down
6 changes: 2 additions & 4 deletions netbox/extras/dashboard/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from django.contrib.contenttypes.models import ContentType
from django.core.cache import cache
from django.db.models import Q
from django.http import QueryDict
from django.template.loader import render_to_string
from django.urls import NoReverseMatch, resolve, reverse
from django.utils.translation import gettext as _
Expand All @@ -19,7 +18,7 @@
from utilities.forms import BootstrapMixin
from utilities.permissions import get_permission_for_model
from utilities.templatetags.builtins.filters import render_markdown
from utilities.utils import content_type_identifier, content_type_name, get_viewname
from utilities.utils import content_type_identifier, content_type_name, dict_to_querydict, get_viewname
from .utils import register_widget

__all__ = (
Expand Down Expand Up @@ -170,8 +169,7 @@ def render(self, request):
qs = model.objects.restrict(request.user, 'view')
# Apply any specified filters
if filters := self.config.get('filters'):
params = QueryDict(mutable=True)
params.update(filters)
params = dict_to_querydict(filters)
filterset = getattr(resolve(url).func.view_class, 'filterset', None)
qs = filterset(params, qs).qs
url = f'{url}?{params.urlencode()}'
Expand Down
4 changes: 2 additions & 2 deletions netbox/extras/models/change_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django.urls import reverse

from extras.choices import *
from utilities.querysets import RestrictedQuerySet
from ..querysets import ObjectChangeQuerySet

__all__ = (
'ObjectChange',
Expand Down Expand Up @@ -82,7 +82,7 @@ class ObjectChange(models.Model):
null=True
)

objects = RestrictedQuerySet.as_manager()
objects = ObjectChangeQuerySet.as_manager()

class Meta:
ordering = ['-time']
Expand Down
9 changes: 4 additions & 5 deletions netbox/extras/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from django.core.cache import cache
from django.core.validators import ValidationError
from django.db import models
from django.http import HttpResponse, QueryDict
from django.http import HttpResponse
from django.urls import reverse
from django.utils import timezone
from django.utils.formats import date_format
Expand All @@ -26,7 +26,7 @@
CloningMixin, CustomFieldsMixin, CustomLinksMixin, ExportTemplatesMixin, SyncedDataMixin, TagsMixin,
)
from utilities.querysets import RestrictedQuerySet
from utilities.utils import clean_html, render_jinja2
from utilities.utils import clean_html, dict_to_querydict, render_jinja2

__all__ = (
'ConfigRevision',
Expand Down Expand Up @@ -285,7 +285,7 @@ def render(self, context):
text = clean_html(text, allowed_schemes)

# Sanitize link
link = urllib.parse.quote(link, safe='/:?&=%+[]@#')
link = urllib.parse.quote(link, safe='/:?&=%+[]@#,')

# Verify link scheme is allowed
result = urllib.parse.urlparse(link)
Expand Down Expand Up @@ -462,8 +462,7 @@ def clean(self):

@property
def url_params(self):
qd = QueryDict(mutable=True)
qd.update(self.parameters)
qd = dict_to_querydict(self.parameters)
return qd.urlencode()


Expand Down
7 changes: 5 additions & 2 deletions netbox/extras/models/reports.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import inspect
import logging
from functools import cached_property

from django.contrib.contenttypes.fields import GenericRelation
from django.db import models
from django.urls import reverse

Expand All @@ -12,6 +12,8 @@
from utilities.querysets import RestrictedQuerySet
from .mixins import PythonModuleMixin

logger = logging.getLogger('netbox.reports')

__all__ = (
'Report',
'ReportModule',
Expand Down Expand Up @@ -56,7 +58,8 @@ def _get_name(cls):

try:
module = self.get_module()
except ImportError:
except (ImportError, SyntaxError) as e:
logger.error(f"Unable to load report module {self.name}, exception: {e}")
return {}
reports = {}
ordered = getattr(module, 'report_order', [])
Expand Down
Loading