diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index d458bc646..e37354d47 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -233,7 +233,7 @@ class WritableRackReservationSerializer(ValidatedModelSerializer): class Meta: model = RackReservation - fields = ['id', 'rack', 'units', 'user', 'description'] + fields = ['id', 'rack', 'units', 'user', 'tenant', 'description'] # diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 924fe67fb..6e7aa070c 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -157,6 +157,7 @@ class RegionBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): permission_required = 'dcim.delete_region' cls = Region queryset = Region.objects.annotate(site_count=Count('sites')) + filter = filters.RegionFilter table = tables.RegionTable default_return_url = 'dcim:region_list' @@ -491,6 +492,7 @@ class RackReservationBulkEditView(PermissionRequiredMixin, BulkEditView): class RackReservationBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): permission_required = 'dcim.delete_rackreservation' cls = RackReservation + filter = filters.RackReservationFilter table = tables.RackReservationTable default_return_url = 'dcim:rackreservation_list' diff --git a/netbox/ipam/fields.py b/netbox/ipam/fields.py index e0842d10b..8c7dbb690 100644 --- a/netbox/ipam/fields.py +++ b/netbox/ipam/fields.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals from django.core.exceptions import ValidationError from django.db import models -from netaddr import IPNetwork +from netaddr import AddrFormatError, IPNetwork from .formfields import IPFormField from . import lookups @@ -26,7 +26,9 @@ class BaseIPField(models.Field): return value try: return IPNetwork(value) - except ValueError as e: + except AddrFormatError as e: + raise ValidationError("Invalid IP address format: {}".format(value)) + except (TypeError, ValueError) as e: raise ValidationError(e) def get_prep_value(self, value): diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 7a8dd1a98..b74cbe7f4 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -22,7 +22,7 @@ if sys.version_info[0] < 3: DeprecationWarning ) -VERSION = '2.3.3' +VERSION = '2.3.4-dev' BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) diff --git a/netbox/templates/dcim/inc/interface.html b/netbox/templates/dcim/inc/interface.html index aa0a9cbd5..33e30b126 100644 --- a/netbox/templates/dcim/inc/interface.html +++ b/netbox/templates/dcim/inc/interface.html @@ -105,7 +105,7 @@ - + {% else %} diff --git a/netbox/templates/dcim/rackrole_list.html b/netbox/templates/dcim/rackrole_list.html index e18bf7941..51cb19781 100644 --- a/netbox/templates/dcim/rackrole_list.html +++ b/netbox/templates/dcim/rackrole_list.html @@ -1,22 +1,17 @@ {% extends '_base.html' %} -{% load helpers %} +{% load buttons %} {% block content %}
{% if perms.dcim.add_rackrole %} - - - Add a rack role - - - - Import rack roles - + {% add_button 'dcim:rackrole_add' %} + {% import_button 'dcim:rackrole_import' %} {% endif %} + {% export_button content_type %}

{% block title %}Rack Roles{% endblock %}

-
+
{% include 'utilities/obj_table.html' with bulk_delete_url='dcim:rackrole_bulk_delete' %}
diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index d060e53d7..94b44fc48 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -626,8 +626,11 @@ class BulkDeleteView(View): return_url = reverse(self.default_return_url) # Are we deleting *all* objects in the queryset or just a selected subset? - if request.POST.get('_all') and self.filter is not None: - pk_list = [obj.pk for obj in self.filter(request.GET, self.cls.objects.only('pk')).qs] + if request.POST.get('_all'): + if self.filter is not None: + pk_list = [obj.pk for obj in self.filter(request.GET, self.cls.objects.only('pk')).qs] + else: + pk_list = self.cls.objects.values_list('pk', flat=True) else: pk_list = [int(pk) for pk in request.POST.getlist('pk')] diff --git a/netbox/virtualization/views.py b/netbox/virtualization/views.py index 6de6b86c7..5aef710c1 100644 --- a/netbox/virtualization/views.py +++ b/netbox/virtualization/views.py @@ -115,7 +115,7 @@ class ClusterView(View): 'site', 'rack', 'tenant', 'device_type__manufacturer' ) device_table = DeviceTable(list(devices), orderable=False) - if request.user.has_perm('virtualization:change_cluster'): + if request.user.has_perm('virtualization.change_cluster'): device_table.columns.show('pk') return render(request, 'virtualization/cluster.html', { @@ -160,6 +160,7 @@ class ClusterBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): permission_required = 'virtualization.delete_cluster' cls = Cluster queryset = Cluster.objects.all() + filter = filters.ClusterFilter table = tables.ClusterTable default_return_url = 'virtualization:cluster_list'