This commit is contained in:
tcastelle 2018-05-22 19:52:53 +00:00 committed by GitHub
commit 0308c9d7b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 21 additions and 18 deletions

View File

@ -233,7 +233,7 @@ class WritableRackReservationSerializer(ValidatedModelSerializer):
class Meta: class Meta:
model = RackReservation model = RackReservation
fields = ['id', 'rack', 'units', 'user', 'description'] fields = ['id', 'rack', 'units', 'user', 'tenant', 'description']
# #

View File

@ -157,6 +157,7 @@ class RegionBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_region' permission_required = 'dcim.delete_region'
cls = Region cls = Region
queryset = Region.objects.annotate(site_count=Count('sites')) queryset = Region.objects.annotate(site_count=Count('sites'))
filter = filters.RegionFilter
table = tables.RegionTable table = tables.RegionTable
default_return_url = 'dcim:region_list' default_return_url = 'dcim:region_list'
@ -491,6 +492,7 @@ class RackReservationBulkEditView(PermissionRequiredMixin, BulkEditView):
class RackReservationBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): class RackReservationBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_rackreservation' permission_required = 'dcim.delete_rackreservation'
cls = RackReservation cls = RackReservation
filter = filters.RackReservationFilter
table = tables.RackReservationTable table = tables.RackReservationTable
default_return_url = 'dcim:rackreservation_list' default_return_url = 'dcim:rackreservation_list'

View File

@ -2,7 +2,7 @@ from __future__ import unicode_literals
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from netaddr import IPNetwork from netaddr import AddrFormatError, IPNetwork
from .formfields import IPFormField from .formfields import IPFormField
from . import lookups from . import lookups
@ -26,7 +26,9 @@ class BaseIPField(models.Field):
return value return value
try: try:
return IPNetwork(value) 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) raise ValidationError(e)
def get_prep_value(self, value): def get_prep_value(self, value):

View File

@ -22,7 +22,7 @@ if sys.version_info[0] < 3:
DeprecationWarning DeprecationWarning
) )
VERSION = '2.3.3' VERSION = '2.3.4-dev'
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

View File

@ -105,7 +105,7 @@
<button class="btn btn-warning btn-xs interface-toggle connected" disabled="disabled" title="Circuits cannot be marked as planned or connected"> <button class="btn btn-warning btn-xs interface-toggle connected" disabled="disabled" title="Circuits cannot be marked as planned or connected">
<i class="glyphicon glyphicon-ban-circle" aria-hidden="true"></i> <i class="glyphicon glyphicon-ban-circle" aria-hidden="true"></i>
</button> </button>
<a href="{% url 'circuits:circuittermination_edit' pk=iface.circuit_termination.pk %}&return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs" title="Edit circuit termination"> <a href="{% url 'circuits:circuittermination_edit' pk=iface.circuit_termination.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs" title="Edit circuit termination">
<i class="glyphicon glyphicon-resize-full" aria-hidden="true"></i> <i class="glyphicon glyphicon-resize-full" aria-hidden="true"></i>
</a> </a>
{% else %} {% else %}

View File

@ -1,22 +1,17 @@
{% extends '_base.html' %} {% extends '_base.html' %}
{% load helpers %} {% load buttons %}
{% block content %} {% block content %}
<div class="pull-right"> <div class="pull-right">
{% if perms.dcim.add_rackrole %} {% if perms.dcim.add_rackrole %}
<a href="{% url 'dcim:rackrole_add' %}" class="btn btn-primary"> {% add_button 'dcim:rackrole_add' %}
<span class="fa fa-plus" aria-hidden="true"></span> {% import_button 'dcim:rackrole_import' %}
Add a rack role
</a>
<a href="{% url 'dcim:rackrole_import' %}" class="btn btn-info">
<span class="fa fa-download" aria-hidden="true"></span>
Import rack roles
</a>
{% endif %} {% endif %}
{% export_button content_type %}
</div> </div>
<h1>{% block title %}Rack Roles{% endblock %}</h1> <h1>{% block title %}Rack Roles{% endblock %}</h1>
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
{% include 'utilities/obj_table.html' with bulk_delete_url='dcim:rackrole_bulk_delete' %} {% include 'utilities/obj_table.html' with bulk_delete_url='dcim:rackrole_bulk_delete' %}
</div> </div>
</div> </div>

View File

@ -626,8 +626,11 @@ class BulkDeleteView(View):
return_url = reverse(self.default_return_url) return_url = reverse(self.default_return_url)
# Are we deleting *all* objects in the queryset or just a selected subset? # Are we deleting *all* objects in the queryset or just a selected subset?
if request.POST.get('_all') and self.filter is not None: if request.POST.get('_all'):
pk_list = [obj.pk for obj in self.filter(request.GET, self.cls.objects.only('pk')).qs] 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: else:
pk_list = [int(pk) for pk in request.POST.getlist('pk')] pk_list = [int(pk) for pk in request.POST.getlist('pk')]

View File

@ -115,7 +115,7 @@ class ClusterView(View):
'site', 'rack', 'tenant', 'device_type__manufacturer' 'site', 'rack', 'tenant', 'device_type__manufacturer'
) )
device_table = DeviceTable(list(devices), orderable=False) 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') device_table.columns.show('pk')
return render(request, 'virtualization/cluster.html', { return render(request, 'virtualization/cluster.html', {
@ -160,6 +160,7 @@ class ClusterBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'virtualization.delete_cluster' permission_required = 'virtualization.delete_cluster'
cls = Cluster cls = Cluster
queryset = Cluster.objects.all() queryset = Cluster.objects.all()
filter = filters.ClusterFilter
table = tables.ClusterTable table = tables.ClusterTable
default_return_url = 'virtualization:cluster_list' default_return_url = 'virtualization:cluster_list'