mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-16 04:02:52 -06:00
Added views to create device component templates
This commit is contained in:
parent
082445c016
commit
009ef41e92
@ -8,7 +8,8 @@ from utilities.forms import BootstrapMixin, SmallTextarea, SelectWithDisabled, C
|
|||||||
Livesearch, CSVDataField, CommentField, BulkImportForm, FlexibleModelChoiceField, ExpandableNameField
|
Livesearch, CSVDataField, CommentField, BulkImportForm, FlexibleModelChoiceField, ExpandableNameField
|
||||||
|
|
||||||
from .models import Site, Rack, RackGroup, Device, Manufacturer, DeviceType, DeviceRole, Platform, ConsolePort, \
|
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
|
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}))
|
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
|
# Devices
|
||||||
#
|
#
|
||||||
|
@ -3,6 +3,8 @@ from django.conf.urls import url
|
|||||||
from secrets.views import secret_add
|
from secrets.views import secret_add
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
from .forms import ConsolePortTemplateForm
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
|
||||||
@ -32,6 +34,16 @@ urlpatterns = [
|
|||||||
url(r'^device-types/(?P<pk>\d+)/$', views.devicetype, name='devicetype'),
|
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+)/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+)/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
|
# Devices
|
||||||
url(r'^devices/$', views.DeviceListView.as_view(), name='device_list'),
|
url(r'^devices/$', views.DeviceListView.as_view(), name='device_list'),
|
||||||
|
@ -3,11 +3,13 @@ import re
|
|||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import permission_required
|
from django.contrib.auth.decorators import permission_required
|
||||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.db.models import Count, ProtectedError
|
from django.db.models import Count, ProtectedError
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.utils.http import urlencode
|
from django.utils.http import urlencode
|
||||||
|
from django.views.generic import View
|
||||||
|
|
||||||
from ipam.models import Prefix, IPAddress, VLAN
|
from ipam.models import Prefix, IPAddress, VLAN
|
||||||
from circuits.models import Circuit
|
from circuits.models import Circuit
|
||||||
@ -25,8 +27,10 @@ from .forms import SiteForm, SiteImportForm, RackForm, RackImportForm, RackBulkE
|
|||||||
PowerPortCreateForm, PowerPortConnectionForm, PowerConnectionImportForm, PowerOutletForm, PowerOutletCreateForm, \
|
PowerPortCreateForm, PowerPortConnectionForm, PowerConnectionImportForm, PowerOutletForm, PowerOutletCreateForm, \
|
||||||
PowerOutletConnectionForm, InterfaceForm, InterfaceCreateForm, InterfaceBulkCreateForm, InterfaceConnectionForm, \
|
PowerOutletConnectionForm, InterfaceForm, InterfaceCreateForm, InterfaceBulkCreateForm, InterfaceConnectionForm, \
|
||||||
InterfaceConnectionDeletionForm, InterfaceConnectionImportForm, ConsoleConnectionFilterForm, \
|
InterfaceConnectionDeletionForm, InterfaceConnectionImportForm, ConsoleConnectionFilterForm, \
|
||||||
PowerConnectionFilterForm, InterfaceConnectionFilterForm, IPAddressForm
|
PowerConnectionFilterForm, InterfaceConnectionFilterForm, IPAddressForm, ConsolePortTemplateForm, \
|
||||||
from .models import Site, Rack, DeviceType, Device, ConsolePort, ConsoleServerPort, PowerPort, PowerOutlet, Interface, \
|
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
|
InterfaceConnection, Module, CONNECTION_STATUS_CONNECTED
|
||||||
from .tables import SiteTable, RackTable, RackBulkEditTable, DeviceTypeTable, DeviceTypeBulkEditTable, DeviceTable, \
|
from .tables import SiteTable, RackTable, RackBulkEditTable, DeviceTypeTable, DeviceTypeBulkEditTable, DeviceTable, \
|
||||||
DeviceBulkEditTable, DeviceImportTable, ConsoleConnectionTable, PowerConnectionTable, InterfaceConnectionTable
|
DeviceBulkEditTable, DeviceImportTable, ConsoleConnectionTable, PowerConnectionTable, InterfaceConnectionTable
|
||||||
@ -428,6 +432,80 @@ class DeviceTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
|
|||||||
redirect_url = 'dcim:devicetype_list'
|
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
|
# 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>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<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>
|
<strong>Console Ports</strong>
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-hover panel-body">
|
<table class="table table-hover panel-body">
|
||||||
@ -88,6 +91,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<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>
|
<strong>Power Ports</strong>
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-hover panel-body">
|
<table class="table table-hover panel-body">
|
||||||
@ -103,6 +109,9 @@
|
|||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<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>
|
<strong>Interfaces</strong>
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-hover panel-body">
|
<table class="table table-hover panel-body">
|
||||||
@ -118,6 +127,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<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>
|
<strong>Console Server Ports</strong>
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-hover panel-body">
|
<table class="table table-hover panel-body">
|
||||||
@ -131,6 +143,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<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>
|
<strong>Power Outlets</strong>
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-hover panel-body">
|
<table class="table table-hover panel-body">
|
||||||
|
Loading…
Reference in New Issue
Block a user