mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Rewrote all DeviceType component template deletion views to utilize BulkDeleteView()
This commit is contained in:
@ -251,6 +251,10 @@ class ConsolePortTemplateForm(forms.ModelForm, BootstrapMixin):
|
||||
fields = ['name_pattern']
|
||||
|
||||
|
||||
class ConsolePortTemplateBulkDeleteForm(ConfirmationForm):
|
||||
pk = forms.ModelMultipleChoiceField(queryset=ConsolePortTemplate.objects.all(), widget=forms.MultipleHiddenInput)
|
||||
|
||||
|
||||
class ConsoleServerPortTemplateForm(forms.ModelForm, BootstrapMixin):
|
||||
name_pattern = ExpandableNameField(label='Name')
|
||||
|
||||
@ -259,6 +263,10 @@ class ConsoleServerPortTemplateForm(forms.ModelForm, BootstrapMixin):
|
||||
fields = ['name_pattern']
|
||||
|
||||
|
||||
class ConsoleServerPortTemplateBulkDeleteForm(ConfirmationForm):
|
||||
pk = forms.ModelMultipleChoiceField(queryset=ConsoleServerPortTemplate.objects.all(), widget=forms.MultipleHiddenInput)
|
||||
|
||||
|
||||
class PowerPortTemplateForm(forms.ModelForm, BootstrapMixin):
|
||||
name_pattern = ExpandableNameField(label='Name')
|
||||
|
||||
|
@ -50,31 +50,29 @@ urlpatterns = [
|
||||
url(r'^device-types/(?P<pk>\d+)/edit/$', views.DeviceTypeEditView.as_view(), name='devicetype_edit'),
|
||||
url(r'^device-types/(?P<pk>\d+)/delete/$', views.DeviceTypeDeleteView.as_view(), name='devicetype_delete'),
|
||||
|
||||
# Component templates
|
||||
url(r'^device-types/(?P<pk>\d+)/console-ports/add/$', views.ConsolePortTemplateAddView.as_view(),
|
||||
name='devicetype_add_consoleport'),
|
||||
url(r'^device-types/(?P<pk>\d+)/console-ports/delete/$', views.component_template_delete,
|
||||
{'model': ConsolePortTemplate}, name='devicetype_delete_consoleport'),
|
||||
url(r'^device-types/(?P<pk>\d+)/console-server-ports/add/$', views.ConsoleServerPortTemplateAddView.as_view(),
|
||||
name='devicetype_add_consoleserverport'),
|
||||
url(r'^device-types/(?P<pk>\d+)/console-server-ports/delete/$', views.component_template_delete,
|
||||
{'model': ConsoleServerPortTemplate}, name='devicetype_delete_consoleserverport'),
|
||||
url(r'^device-types/(?P<pk>\d+)/power-ports/add/$', views.PowerPortTemplateAddView.as_view(),
|
||||
name='devicetype_add_powerport'),
|
||||
url(r'^device-types/(?P<pk>\d+)/power-ports/delete/$', views.component_template_delete,
|
||||
{'model': PowerPortTemplate}, name='devicetype_delete_powerport'),
|
||||
url(r'^device-types/(?P<pk>\d+)/power-outlets/add/$', views.PowerOutletTemplateAddView.as_view(),
|
||||
name='devicetype_add_poweroutlet'),
|
||||
url(r'^device-types/(?P<pk>\d+)/power-outlets/delete/$', views.component_template_delete,
|
||||
{'model': PowerOutletTemplate}, name='devicetype_delete_poweroutlet'),
|
||||
url(r'^device-types/(?P<pk>\d+)/interfaces/add/$', views.InterfaceTemplateAddView.as_view(),
|
||||
name='devicetype_add_interface'),
|
||||
url(r'^device-types/(?P<pk>\d+)/interfaces/delete/$', views.component_template_delete,
|
||||
{'model': InterfaceTemplate}, name='devicetype_delete_interface'),
|
||||
url(r'^device-types/(?P<pk>\d+)/device-bays/add/$', views.DeviceBayTemplateAddView.as_view(),
|
||||
name='devicetype_add_devicebay'),
|
||||
url(r'^device-types/(?P<pk>\d+)/device-bays/delete/$', views.component_template_delete,
|
||||
{'model': DeviceBayTemplate}, name='devicetype_delete_devicebay'),
|
||||
# Console port templates
|
||||
url(r'^device-types/(?P<pk>\d+)/console-ports/add/$', views.ConsolePortTemplateAddView.as_view(), name='devicetype_add_consoleport'),
|
||||
url(r'^device-types/(?P<pk>\d+)/console-ports/delete/$', views.ConsolePortTemplateBulkDeleteView.as_view(), name='devicetype_delete_consoleport'),
|
||||
|
||||
# Console server port templates
|
||||
url(r'^device-types/(?P<pk>\d+)/console-server-ports/add/$', views.ConsoleServerPortTemplateAddView.as_view(), name='devicetype_add_consoleserverport'),
|
||||
url(r'^device-types/(?P<pk>\d+)/console-server-ports/delete/$', views.ConsoleServerPortTemplateBulkDeleteView.as_view(), name='devicetype_delete_consoleserverport'),
|
||||
|
||||
# Power port templates
|
||||
url(r'^device-types/(?P<pk>\d+)/power-ports/add/$', views.PowerPortTemplateAddView.as_view(), name='devicetype_add_powerport'),
|
||||
url(r'^device-types/(?P<pk>\d+)/power-ports/delete/$', views.PowerPortTemplateBulkDeleteView.as_view(), name='devicetype_delete_powerport'),
|
||||
|
||||
# Power outlet templates
|
||||
url(r'^device-types/(?P<pk>\d+)/power-outlets/add/$', views.PowerOutletTemplateAddView.as_view(), name='devicetype_add_poweroutlet'),
|
||||
url(r'^device-types/(?P<pk>\d+)/power-outlets/delete/$', views.PowerOutletTemplateBulkDeleteView.as_view(), name='devicetype_delete_poweroutlet'),
|
||||
|
||||
# Interface templates
|
||||
url(r'^device-types/(?P<pk>\d+)/interfaces/add/$', views.InterfaceTemplateAddView.as_view(), name='devicetype_add_interface'),
|
||||
url(r'^device-types/(?P<pk>\d+)/interfaces/delete/$', views.InterfaceTemplateBulkDeleteView.as_view(), name='devicetype_delete_interface'),
|
||||
|
||||
# Device bay templates
|
||||
url(r'^device-types/(?P<pk>\d+)/device-bays/add/$', views.DeviceBayTemplateAddView.as_view(), name='devicetype_add_devicebay'),
|
||||
url(r'^device-types/(?P<pk>\d+)/device-bays/delete/$', views.DeviceBayTemplateBulkDeleteView.as_view(), name='devicetype_delete_devicebay'),
|
||||
|
||||
# Device roles
|
||||
url(r'^device-roles/$', views.DeviceRoleListView.as_view(), name='devicerole_list'),
|
||||
|
@ -7,8 +7,7 @@ from django.contrib.auth.decorators import permission_required
|
||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db.models import Count, ProtectedError, Sum
|
||||
from django.forms import ModelMultipleChoiceField, MultipleHiddenInput
|
||||
from django.db.models import Count, Sum
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.utils.http import urlencode
|
||||
@ -17,7 +16,6 @@ from django.views.generic import View
|
||||
from ipam.models import Prefix, IPAddress, VLAN
|
||||
from circuits.models import Circuit
|
||||
from extras.models import TopologyMap
|
||||
from utilities.error_handlers import handle_protectederror
|
||||
from utilities.forms import ConfirmationForm
|
||||
from utilities.views import (
|
||||
BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
|
||||
@ -396,68 +394,65 @@ class ConsolePortTemplateAddView(ComponentTemplateCreateView):
|
||||
form = forms.ConsolePortTemplateForm
|
||||
|
||||
|
||||
class ConsolePortTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||
permission_required = 'dcim.delete_consoleporttemplate'
|
||||
cls = ConsolePortTemplate
|
||||
parent_cls = DeviceType
|
||||
|
||||
|
||||
class ConsoleServerPortTemplateAddView(ComponentTemplateCreateView):
|
||||
model = ConsoleServerPortTemplate
|
||||
form = forms.ConsoleServerPortTemplateForm
|
||||
|
||||
|
||||
class ConsoleServerPortTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||
permission_required = 'dcim.delete_consoleserverporttemplate'
|
||||
cls = ConsoleServerPortTemplate
|
||||
parent_cls = DeviceType
|
||||
|
||||
|
||||
class PowerPortTemplateAddView(ComponentTemplateCreateView):
|
||||
model = PowerPortTemplate
|
||||
form = forms.PowerPortTemplateForm
|
||||
|
||||
|
||||
class PowerPortTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||
permission_required = 'dcim.delete_powerporttemplate'
|
||||
cls = PowerPortTemplate
|
||||
parent_cls = DeviceType
|
||||
|
||||
|
||||
class PowerOutletTemplateAddView(ComponentTemplateCreateView):
|
||||
model = PowerOutletTemplate
|
||||
form = forms.PowerOutletTemplateForm
|
||||
|
||||
|
||||
class PowerOutletTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||
permission_required = 'dcim.delete_poweroutlettemplate'
|
||||
cls = PowerOutletTemplate
|
||||
parent_cls = DeviceType
|
||||
|
||||
|
||||
class InterfaceTemplateAddView(ComponentTemplateCreateView):
|
||||
model = InterfaceTemplate
|
||||
form = forms.InterfaceTemplateForm
|
||||
|
||||
|
||||
class InterfaceTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||
permission_required = 'dcim.delete_interfacetemplate'
|
||||
cls = InterfaceTemplate
|
||||
parent_cls = DeviceType
|
||||
|
||||
|
||||
class DeviceBayTemplateAddView(ComponentTemplateCreateView):
|
||||
model = DeviceBayTemplate
|
||||
form = forms.DeviceBayTemplateForm
|
||||
|
||||
|
||||
def component_template_delete(request, pk, model):
|
||||
|
||||
devicetype = get_object_or_404(DeviceType, pk=pk)
|
||||
|
||||
class ComponentTemplateBulkDeleteForm(ConfirmationForm):
|
||||
pk = ModelMultipleChoiceField(queryset=model.objects.all(), widget=MultipleHiddenInput)
|
||||
|
||||
if '_confirm' in request.POST:
|
||||
form = ComponentTemplateBulkDeleteForm(request.POST)
|
||||
if form.is_valid():
|
||||
|
||||
# Delete component templates
|
||||
objects_to_delete = model.objects.filter(pk__in=[v.id for v in form.cleaned_data['pk']])
|
||||
try:
|
||||
deleted_count = objects_to_delete.count()
|
||||
objects_to_delete.delete()
|
||||
except ProtectedError, e:
|
||||
handle_protectederror(list(objects_to_delete), request, e)
|
||||
return redirect('dcim:devicetype', {'pk': devicetype.pk})
|
||||
|
||||
messages.success(request, "Deleted {} {}".format(deleted_count, model._meta.verbose_name_plural))
|
||||
return redirect('dcim:devicetype', pk=devicetype.pk)
|
||||
|
||||
else:
|
||||
form = ComponentTemplateBulkDeleteForm(initial={'pk': request.POST.getlist('pk')})
|
||||
|
||||
selected_objects = model.objects.filter(pk__in=request.POST.getlist('pk'))
|
||||
if not selected_objects:
|
||||
messages.warning(request, "No {} were selected for deletion.".format(model._meta.verbose_name_plural))
|
||||
return redirect('dcim:devicetype', pk=devicetype.pk)
|
||||
|
||||
return render(request, 'dcim/component_template_delete.html', {
|
||||
'devicetype': devicetype,
|
||||
'form': form,
|
||||
'selected_objects': selected_objects,
|
||||
'cancel_url': reverse('dcim:devicetype', kwargs={'pk': devicetype.pk}),
|
||||
})
|
||||
class DeviceBayTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||
permission_required = 'dcim.delete_devicebaytemplate'
|
||||
cls = DeviceBayTemplate
|
||||
parent_cls = DeviceType
|
||||
|
||||
|
||||
#
|
||||
|
@ -5,11 +5,15 @@
|
||||
|
||||
{% block message %}
|
||||
<p>
|
||||
Are you sure you want to delete these {{ obj_type_plural|default:"objects" }}?
|
||||
Are you sure you want to delete these {{ obj_type_plural|default:"objects" }}{% if parent_obj %} from <a href="{{ parent_obj.get_absolute_url }}">{{ parent_obj }}</a>{% endif %}?
|
||||
</p>
|
||||
<ul>
|
||||
{% for obj in selected_objects %}
|
||||
<li><a href="{{ obj.get_absolute_url }}">{{ obj }}</a></li>
|
||||
{% if obj.get_absolute_url %}
|
||||
<li><a href="{{ obj.get_absolute_url }}">{{ obj }}</a></li>
|
||||
{% else %}
|
||||
<li>{{ obj }}</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
@ -3,9 +3,11 @@ from django_tables2 import RequestConfig
|
||||
from django.contrib import messages
|
||||
from django.contrib.admin.views.decorators import staff_member_required
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import transaction, IntegrityError
|
||||
from django.db.models import ProtectedError
|
||||
from django.forms import ModelMultipleChoiceField, MultipleHiddenInput
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.template import TemplateSyntaxError
|
||||
@ -309,6 +311,7 @@ class BulkEditView(View):
|
||||
|
||||
class BulkDeleteView(View):
|
||||
cls = None
|
||||
parent_cls = None
|
||||
form = None
|
||||
template_name = 'utilities/confirm_bulk_delete.html'
|
||||
default_redirect_url = None
|
||||
@ -317,24 +320,35 @@ class BulkDeleteView(View):
|
||||
def dispatch(self, *args, **kwargs):
|
||||
return super(BulkDeleteView, self).dispatch(*args, **kwargs)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return redirect(self.default_redirect_url)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
|
||||
# Attempt to derive parent object if a parent class has been given
|
||||
if self.parent_cls:
|
||||
parent_obj = get_object_or_404(self.parent_cls, **kwargs)
|
||||
else:
|
||||
parent_obj = None
|
||||
|
||||
# Determine URL to redirect users upon deletion of objects
|
||||
posted_redirect_url = request.POST.get('redirect_url')
|
||||
if posted_redirect_url and is_safe_url(url=posted_redirect_url, host=request.get_host()):
|
||||
redirect_url = posted_redirect_url
|
||||
else:
|
||||
elif parent_obj:
|
||||
redirect_url = parent_obj.get_absolute_url()
|
||||
elif self.default_redirect_url:
|
||||
redirect_url = reverse(self.default_redirect_url)
|
||||
else:
|
||||
raise ImproperlyConfigured('No redirect URL has been provided.')
|
||||
|
||||
# Are we deleting *all* objects in the queryset or just a selected subset?
|
||||
if request.POST.get('_all'):
|
||||
pk_list = [x for x in request.POST.get('pk_all').split(',') if x]
|
||||
else:
|
||||
pk_list = request.POST.getlist('pk')
|
||||
|
||||
form_cls = self.get_form()
|
||||
|
||||
if '_confirm' in request.POST:
|
||||
form = self.form(request.POST)
|
||||
form = form_cls(request.POST)
|
||||
if form.is_valid():
|
||||
|
||||
# Delete objects
|
||||
@ -351,7 +365,7 @@ class BulkDeleteView(View):
|
||||
return redirect(redirect_url)
|
||||
|
||||
else:
|
||||
form = self.form(initial={'pk': pk_list})
|
||||
form = form_cls(initial={'pk': pk_list})
|
||||
|
||||
selected_objects = self.cls.objects.filter(pk__in=pk_list)
|
||||
if not selected_objects:
|
||||
@ -360,7 +374,18 @@ class BulkDeleteView(View):
|
||||
|
||||
return render(request, self.template_name, {
|
||||
'form': form,
|
||||
'parent_obj': parent_obj,
|
||||
'obj_type_plural': self.cls._meta.verbose_name_plural,
|
||||
'selected_objects': selected_objects,
|
||||
'cancel_url': redirect_url,
|
||||
})
|
||||
|
||||
def get_form(self):
|
||||
"""Provide a standard bulk delete form if none has been specified for the view"""
|
||||
|
||||
class BulkDeleteForm(ConfirmationForm):
|
||||
pk = ModelMultipleChoiceField(queryset=self.cls.objects.all(), widget=MultipleHiddenInput)
|
||||
|
||||
if self.form:
|
||||
return self.form
|
||||
return BulkDeleteForm
|
||||
|
Reference in New Issue
Block a user