mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-09 00:58:16 -06:00
Merge afba80bff9
into 328958876a
This commit is contained in:
commit
0308c9d7b8
@ -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']
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -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'
|
||||||
|
|
||||||
|
@ -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):
|
||||||
|
@ -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__)))
|
||||||
|
|
||||||
|
@ -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 %}
|
||||||
|
@ -1,18 +1,13 @@
|
|||||||
{% 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">
|
||||||
|
@ -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'):
|
||||||
|
if self.filter is not None:
|
||||||
pk_list = [obj.pk for obj in self.filter(request.GET, self.cls.objects.only('pk')).qs]
|
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')]
|
||||||
|
|
||||||
|
@ -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'
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user