1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #181: Implemented support for bulk IP address creation

This commit is contained in:
Jeremy Stretch
2016-12-20 15:39:22 -05:00
parent f0d8e02d63
commit 9fd9719d0b
8 changed files with 106 additions and 8 deletions

View File

@ -5,7 +5,8 @@ from dcim.models import Site, Rack, Device, Interface
from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
from tenancy.models import Tenant
from utilities.forms import (
APISelect, BootstrapMixin, CSVDataField, BulkImportForm, FilterChoiceField, Livesearch, SlugField, add_blank_choice,
APISelect, BootstrapMixin, BulkImportForm, CSVDataField, ExpandableIPAddressField, FilterChoiceField, Livesearch,
SlugField, add_blank_choice,
)
from .models import (
@ -339,6 +340,14 @@ class IPAddressForm(BootstrapMixin, CustomFieldForm):
self.fields['nat_inside'].choices = []
class IPAddressBulkAddForm(forms.Form, BootstrapMixin):
address = ExpandableIPAddressField()
vrf = forms.ModelChoiceField(queryset=VRF.objects.all(), required=False, label='VRF')
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
status = forms.ChoiceField(choices=IPADDRESS_STATUS_CHOICES)
description = forms.CharField(max_length=100, required=False)
class IPAddressAssignForm(BootstrapMixin, forms.Form):
site = forms.ModelChoiceField(queryset=Site.objects.all(), label='Site', required=False,
widget=forms.Select(attrs={'filter-for': 'rack'}))

View File

@ -51,6 +51,7 @@ urlpatterns = [
# IP addresses
url(r'^ip-addresses/$', views.IPAddressListView.as_view(), name='ipaddress_list'),
url(r'^ip-addresses/add/$', views.IPAddressEditView.as_view(), name='ipaddress_add'),
url(r'^ip-addresses/bulk-add/$', views.IPAddressBulkAddView.as_view(), name='ipaddress_bulk_add'),
url(r'^ip-addresses/import/$', views.IPAddressBulkImportView.as_view(), name='ipaddress_import'),
url(r'^ip-addresses/edit/$', views.IPAddressBulkEditView.as_view(), name='ipaddress_bulk_edit'),
url(r'^ip-addresses/delete/$', views.IPAddressBulkDeleteView.as_view(), name='ipaddress_bulk_delete'),

View File

@ -12,7 +12,7 @@ from dcim.models import Device
from utilities.forms import ConfirmationForm
from utilities.paginator import EnhancedPaginator
from utilities.views import (
BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
BulkAddView, BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
)
from . import filters, forms, tables
@ -613,6 +613,14 @@ class IPAddressDeleteView(PermissionRequiredMixin, ObjectDeleteView):
redirect_url = 'ipam:ipaddress_list'
class IPAddressBulkAddView(PermissionRequiredMixin, BulkAddView):
permission_required = 'ipam.add_ipaddress'
form = forms.IPAddressBulkAddForm
model = IPAddress
template_name = 'ipam/ipaddress_bulk_add.html'
redirect_url = 'ipam:ipaddress_list'
class IPAddressBulkImportView(PermissionRequiredMixin, BulkImportView):
permission_required = 'ipam.add_ipaddress'
form = forms.IPAddressImportForm

View File

@ -0,0 +1,4 @@
<ul class="nav nav-tabs" style="margin-bottom: 20px">
<li role="presentation"{% if active_tab == 'add' %} class="active"{% endif %}><a href="{% url 'ipam:ipaddress_add' %}">Individual</a></li>
<li role="presentation"{% if active_tab == 'bulk_add' %} class="active"{% endif %}><a href="{% url 'ipam:ipaddress_bulk_add' %}">Bulk</a></li>
</ul>

View File

@ -0,0 +1,22 @@
{% extends 'utilities/obj_edit.html' %}
{% load static from staticfiles %}
{% load form_helpers %}
{% block title %}Bulk Add IP Addresses{% endblock %}
{% block tabs %}
{% include 'ipam/inc/ipadress_edit_header.html' with active_tab='bulk_add' %}
{% endblock %}
{% block form %}
<div class="panel panel-default">
<div class="panel-heading"><strong>IP Address</strong></div>
<div class="panel-body">
{% render_field form.address %}
{% render_field form.vrf %}
{% render_field form.tenant %}
{% render_field form.status %}
{% render_field form.description %}
</div>
</div>
{% endblock %}

View File

@ -2,6 +2,12 @@
{% load static from staticfiles %}
{% load form_helpers %}
{% block tabs %}
{% if not obj.pk %}
{% include 'ipam/inc/ipadress_edit_header.html' with active_tab='add' %}
{% endif %}
{% endblock %}
{% block form %}
<div class="panel panel-default">
<div class="panel-heading"><strong>IP Address</strong></div>

View File

@ -1,10 +1,6 @@
{% extends '_base.html' %}
{% load form_helpers %}
{% block title %}
{% if obj.pk %}Editing {{ obj_type }} {{ obj }}{% else %}Add a new {{ obj_type }}{% endif %}
{% endblock %}
{% block content %}
<form action="." method="post" class="form form-horizontal">
{% csrf_token %}
@ -13,7 +9,8 @@
{% endfor %}
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h3>{% if obj.pk %}Editing {{ obj_type }} {{ obj }}{% else %}Add a new {{ obj_type }}{% endif %}</h3>
<h3>{% block title %}{% if obj.pk %}Editing {{ obj_type }} {{ obj }}{% else %}Add a new {{ obj_type }}{% endif %}{% endblock %}</h3>
{% block tabs %}{% endblock %}
{% if form.non_field_errors %}
<div class="panel panel-danger">
<div class="panel-heading"><strong>Errors</strong></div>

View File

@ -3,7 +3,7 @@ from django_tables2 import RequestConfig
from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ImproperlyConfigured
from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.core.urlresolvers import reverse
from django.db import transaction, IntegrityError
from django.db.models import ProtectedError
@ -254,6 +254,57 @@ class ObjectDeleteView(View):
})
class BulkAddView(View):
form = None
model = None
template_name = None
redirect_url = None
def get(self, request):
form = self.form()
return render(request, self.template_name, {
'obj_type': self.model._meta.verbose_name,
'form': form,
'cancel_url': reverse(self.redirect_url),
})
def post(self, request):
form = self.form(request.POST)
if form.is_valid():
# The first field will be used as the pattern
pattern_field = form.fields.keys()[0]
pattern = form.cleaned_data[pattern_field]
# All other fields will be copied as object attributes
kwargs = {k: form.cleaned_data[k] for k in form.fields.keys()[1:]}
new_objs = []
try:
with transaction.atomic():
for value in pattern:
obj = self.model(**kwargs)
setattr(obj, pattern_field, value)
obj.full_clean()
obj.save()
new_objs.append(obj)
except ValidationError as e:
form.add_error(None, e)
if not form.errors:
messages.success(request, u"Added {} {}.".format(len(new_objs), self.model._meta.verbose_name_plural))
return redirect(self.redirect_url)
return render(request, self.template_name, {
'form': form,
'obj_type': self.model._meta.verbose_name,
'cancel_url': reverse(self.redirect_url),
})
class BulkImportView(View):
form = None
table = None