mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Added views to create device component templates
This commit is contained in:
@ -8,7 +8,8 @@ from utilities.forms import BootstrapMixin, SmallTextarea, SelectWithDisabled, C
|
||||
Livesearch, CSVDataField, CommentField, BulkImportForm, FlexibleModelChoiceField, ExpandableNameField
|
||||
|
||||
from .models import Site, Rack, RackGroup, Device, Manufacturer, DeviceType, DeviceRole, Platform, ConsolePort, \
|
||||
ConsoleServerPort, PowerPort, PowerOutlet, Interface, InterfaceConnection, CONNECTION_STATUS_CHOICES, \
|
||||
ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, PowerPort, PowerPortTemplate, PowerOutlet, \
|
||||
PowerOutletTemplate, Interface, InterfaceTemplate, InterfaceConnection, CONNECTION_STATUS_CHOICES, \
|
||||
CONNECTION_STATUS_PLANNED, CONNECTION_STATUS_CONNECTED, IFACE_FF_VIRTUAL, STATUS_CHOICES
|
||||
|
||||
|
||||
@ -191,6 +192,50 @@ class DeviceTypeFilterForm(forms.Form, BootstrapMixin):
|
||||
widget=forms.SelectMultiple(attrs={'size': 8}))
|
||||
|
||||
|
||||
#
|
||||
# Device component templates
|
||||
#
|
||||
|
||||
class ConsolePortTemplateForm(forms.ModelForm, BootstrapMixin):
|
||||
name_pattern = ExpandableNameField(label='Name')
|
||||
|
||||
class Meta:
|
||||
model = ConsolePortTemplate
|
||||
fields = ['name_pattern']
|
||||
|
||||
|
||||
class ConsoleServerPortTemplateForm(forms.ModelForm, BootstrapMixin):
|
||||
name_pattern = ExpandableNameField(label='Name')
|
||||
|
||||
class Meta:
|
||||
model = ConsoleServerPortTemplate
|
||||
fields = ['name_pattern']
|
||||
|
||||
|
||||
class PowerPortTemplateForm(forms.ModelForm, BootstrapMixin):
|
||||
name_pattern = ExpandableNameField(label='Name')
|
||||
|
||||
class Meta:
|
||||
model = PowerPortTemplate
|
||||
fields = ['name_pattern']
|
||||
|
||||
|
||||
class PowerOutletTemplateForm(forms.ModelForm, BootstrapMixin):
|
||||
name_pattern = ExpandableNameField(label='Name')
|
||||
|
||||
class Meta:
|
||||
model = PowerOutletTemplate
|
||||
fields = ['name_pattern']
|
||||
|
||||
|
||||
class InterfaceTemplateForm(forms.ModelForm, BootstrapMixin):
|
||||
name_pattern = ExpandableNameField(label='Name')
|
||||
|
||||
class Meta:
|
||||
model = InterfaceTemplate
|
||||
fields = ['name_pattern', 'form_factor', 'mgmt_only']
|
||||
|
||||
|
||||
#
|
||||
# Devices
|
||||
#
|
||||
|
@ -3,6 +3,8 @@ from django.conf.urls import url
|
||||
from secrets.views import secret_add
|
||||
|
||||
from . import views
|
||||
from .forms import ConsolePortTemplateForm
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
|
||||
@ -32,6 +34,16 @@ urlpatterns = [
|
||||
url(r'^device-types/(?P<pk>\d+)/$', views.devicetype, name='devicetype'),
|
||||
url(r'^device-types/(?P<pk>\d+)/edit/$', views.devicetype_edit, name='devicetype_edit'),
|
||||
url(r'^device-types/(?P<pk>\d+)/delete/$', views.devicetype_delete, name='devicetype_delete'),
|
||||
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-server-ports/add/$', views.ConsolePortTemplateAddView.as_view(),
|
||||
name='devicetype_add_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-outlets/add/$', views.PowerOutletTemplateAddView.as_view(),
|
||||
name='devicetype_add_poweroutlet'),
|
||||
url(r'^device-types/(?P<pk>\d+)/interfaces/add/$', views.InterfaceTemplateAddView.as_view(),
|
||||
name='devicetype_add_interface'),
|
||||
|
||||
# Devices
|
||||
url(r'^devices/$', views.DeviceListView.as_view(), name='device_list'),
|
||||
|
@ -3,11 +3,13 @@ import re
|
||||
from django.contrib import messages
|
||||
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
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.utils.http import urlencode
|
||||
from django.views.generic import View
|
||||
|
||||
from ipam.models import Prefix, IPAddress, VLAN
|
||||
from circuits.models import Circuit
|
||||
@ -25,8 +27,10 @@ from .forms import SiteForm, SiteImportForm, RackForm, RackImportForm, RackBulkE
|
||||
PowerPortCreateForm, PowerPortConnectionForm, PowerConnectionImportForm, PowerOutletForm, PowerOutletCreateForm, \
|
||||
PowerOutletConnectionForm, InterfaceForm, InterfaceCreateForm, InterfaceBulkCreateForm, InterfaceConnectionForm, \
|
||||
InterfaceConnectionDeletionForm, InterfaceConnectionImportForm, ConsoleConnectionFilterForm, \
|
||||
PowerConnectionFilterForm, InterfaceConnectionFilterForm, IPAddressForm
|
||||
from .models import Site, Rack, DeviceType, Device, ConsolePort, ConsoleServerPort, PowerPort, PowerOutlet, Interface, \
|
||||
PowerConnectionFilterForm, InterfaceConnectionFilterForm, IPAddressForm, ConsolePortTemplateForm, \
|
||||
ConsoleServerPortTemplateForm, PowerPortTemplateForm, PowerOutletTemplateForm, InterfaceTemplateForm
|
||||
from .models import Site, Rack, DeviceType, ConsolePortTemplate, ConsoleServerPortTemplate, PowerPortTemplate, \
|
||||
PowerOutletTemplate, InterfaceTemplate, Device, ConsolePort, ConsoleServerPort, PowerPort, PowerOutlet, Interface, \
|
||||
InterfaceConnection, Module, CONNECTION_STATUS_CONNECTED
|
||||
from .tables import SiteTable, RackTable, RackBulkEditTable, DeviceTypeTable, DeviceTypeBulkEditTable, DeviceTable, \
|
||||
DeviceBulkEditTable, DeviceImportTable, ConsoleConnectionTable, PowerConnectionTable, InterfaceConnectionTable
|
||||
@ -428,6 +432,80 @@ class DeviceTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
||||
redirect_url = 'dcim:devicetype_list'
|
||||
|
||||
|
||||
class ComponentTemplateCreateView(View):
|
||||
model = None
|
||||
form = None
|
||||
|
||||
def get(self, request, pk, *args, **kwargs):
|
||||
|
||||
devicetype = get_object_or_404(DeviceType, pk=pk)
|
||||
|
||||
return render(request, 'dcim/component_template_add.html', {
|
||||
'devicetype': devicetype,
|
||||
'component_type': self.model._meta.verbose_name,
|
||||
'form': self.form(),
|
||||
'cancel_url': reverse('dcim:devicetype', kwargs={'pk': devicetype.pk}),
|
||||
})
|
||||
|
||||
def post(self, request, pk, *args, **kwargs):
|
||||
|
||||
devicetype = get_object_or_404(DeviceType, pk=pk)
|
||||
|
||||
form = self.form(request.POST)
|
||||
if form.is_valid():
|
||||
|
||||
component_templates = []
|
||||
for name in form.cleaned_data['name_pattern']:
|
||||
component_template = self.form(request.POST).save(commit=False)
|
||||
component_template.device_type = devicetype
|
||||
component_template.name = name
|
||||
try:
|
||||
component_template.full_clean()
|
||||
component_templates.append(component_template)
|
||||
except ValidationError:
|
||||
form.add_error('name_pattern', "Duplicate name found: {}".format(name))
|
||||
|
||||
if not form.errors:
|
||||
self.model.objects.bulk_create(component_templates)
|
||||
messages.success(request, "Added {} compontent(s) to {}".format(len(component_templates), devicetype))
|
||||
if '_addanother' in request.POST:
|
||||
return redirect(request.path)
|
||||
else:
|
||||
return redirect('dcim:devicetype', pk=devicetype.pk)
|
||||
|
||||
return render(request, 'dcim/component_template_add.html', {
|
||||
'devicetype': devicetype,
|
||||
'component_type': self.model._meta.verbose_name,
|
||||
'form': form,
|
||||
'cancel_url': reverse('dcim:devicetype', kwargs={'pk': devicetype.pk}),
|
||||
})
|
||||
|
||||
|
||||
class ConsolePortTemplateAddView(ComponentTemplateCreateView):
|
||||
model = ConsolePortTemplate
|
||||
form = ConsolePortTemplateForm
|
||||
|
||||
|
||||
class ConsoleServerPortTemplateAddView(ComponentTemplateCreateView):
|
||||
model = ConsoleServerPortTemplate
|
||||
form = ConsoleServerPortTemplateForm
|
||||
|
||||
|
||||
class PowerPortTemplateAddView(ComponentTemplateCreateView):
|
||||
model = PowerPortTemplate
|
||||
form = PowerPortTemplateForm
|
||||
|
||||
|
||||
class PowerOutletTemplateAddView(ComponentTemplateCreateView):
|
||||
model = PowerOutletTemplate
|
||||
form = PowerOutletTemplateForm
|
||||
|
||||
|
||||
class InterfaceTemplateAddView(ComponentTemplateCreateView):
|
||||
model = InterfaceTemplate
|
||||
form = InterfaceTemplateForm
|
||||
|
||||
|
||||
#
|
||||
# Devices
|
||||
#
|
||||
|
42
netbox/templates/dcim/component_template_add.html
Normal file
42
netbox/templates/dcim/component_template_add.html
Normal file
@ -0,0 +1,42 @@
|
||||
{% extends '_base.html' %}
|
||||
{% load form_helpers %}
|
||||
|
||||
{% block title %}Add {{ component_type }} to {{ devicetype }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form action="." method="post" class="form form-horizontal">
|
||||
{% csrf_token %}
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
{% if form.non_field_errors %}
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading"><strong>Errors</strong></div>
|
||||
<div class="panel-body">
|
||||
{{ form.non_field_errors }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<strong>New {{ component_type }}</strong>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label required">Device Type</label>
|
||||
<div class="col-md-9">
|
||||
<p class="form-control-static">{{ devicetype }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% render_form form %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<button type="submit" name="_update" class="btn btn-primary">Save</button>
|
||||
<a href="{{ cancel_url }}" class="btn btn-default">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
@ -75,6 +75,9 @@
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{% if perms.dcim.change_devicetype %}
|
||||
<a href="{% url 'dcim:devicetype_add_consoleport' pk=devicetype.pk %}" class="btn btn-primary btn-xs pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Console Ports</a>
|
||||
{% endif %}
|
||||
<strong>Console Ports</strong>
|
||||
</div>
|
||||
<table class="table table-hover panel-body">
|
||||
@ -88,6 +91,9 @@
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{% if perms.dcim.change_devicetype %}
|
||||
<a href="{% url 'dcim:devicetype_add_powerport' pk=devicetype.pk %}" class="btn btn-primary btn-xs pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Power Ports</a>
|
||||
{% endif %}
|
||||
<strong>Power Ports</strong>
|
||||
</div>
|
||||
<table class="table table-hover panel-body">
|
||||
@ -103,6 +109,9 @@
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{% if perms.dcim.change_devicetype %}
|
||||
<a href="{% url 'dcim:devicetype_add_interface' pk=devicetype.pk %}" class="btn btn-primary btn-xs pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Interfaces</a>
|
||||
{% endif %}
|
||||
<strong>Interfaces</strong>
|
||||
</div>
|
||||
<table class="table table-hover panel-body">
|
||||
@ -118,6 +127,9 @@
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{% if perms.dcim.change_devicetype %}
|
||||
<a href="{% url 'dcim:devicetype_add_consoleserverport' pk=devicetype.pk %}" class="btn btn-primary btn-xs pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Console Server Ports</a>
|
||||
{% endif %}
|
||||
<strong>Console Server Ports</strong>
|
||||
</div>
|
||||
<table class="table table-hover panel-body">
|
||||
@ -131,6 +143,9 @@
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{% if perms.dcim.change_devicetype %}
|
||||
<a href="{% url 'dcim:devicetype_add_poweroutlet' pk=devicetype.pk %}" class="btn btn-primary btn-xs pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Power Outlet</a>
|
||||
{% endif %}
|
||||
<strong>Power Outlets</strong>
|
||||
</div>
|
||||
<table class="table table-hover panel-body">
|
||||
|
Reference in New Issue
Block a user