diff --git a/README.md b/README.md index f2b430929..66c35250b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,3 @@ -**The [2017 NetBox User Survey](https://goo.gl/forms/75HnNS2iE0Y1hVFH3) is open!** Please consider taking a moment to respond. Your feedback helps shape the pace and focus of NetBox development. The survey will remain open until 2017-03-31. Results will be published on the mailing list. - ---- -  NetBox is an IP address management (IPAM) and data center infrastructure management (DCIM) tool. Initially conceived by the network engineering team at [DigitalOcean](https://www.digitalocean.com/), NetBox was developed specifically to address the needs of network and infrastructure engineers. diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 0e09adbb2..e2cd829b8 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -1481,7 +1481,7 @@ class InterfaceConnectionForm(BootstrapMixin, forms.ModelForm): super(InterfaceConnectionForm, self).__init__(*args, **kwargs) # Initialize interface A choices - device_a_interfaces = Interface.objects.filter(device=device_a).exclude( + device_a_interfaces = Interface.objects.order_naturally().filter(device=device_a).exclude( form_factor__in=VIRTUAL_IFACE_TYPES ).select_related( 'circuit_termination', 'connected_as_a', 'connected_as_b' diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 246fe06f0..f2b042599 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1450,9 +1450,10 @@ def interfaceconnection_add(request, pk): )) if '_addanother' in request.POST: base_url = reverse('dcim:interfaceconnection_add', kwargs={'pk': device.pk}) + device_b = interfaceconnection.interface_b.device params = urlencode({ - 'rack_b': interfaceconnection.interface_b.device.rack.pk, - 'device_b': interfaceconnection.interface_b.device.pk, + 'rack_b': device_b.rack.pk if device_b.rack else '', + 'device_b': device_b.pk, }) return HttpResponseRedirect('{}?{}'.format(base_url, params)) else: diff --git a/netbox/extras/models.py b/netbox/extras/models.py index f06d0aa29..b46c27f87 100644 --- a/netbox/extras/models.py +++ b/netbox/extras/models.py @@ -56,13 +56,15 @@ ACTION_EDIT = 3 ACTION_BULK_EDIT = 4 ACTION_DELETE = 5 ACTION_BULK_DELETE = 6 +ACTION_BULK_CREATE = 7 ACTION_CHOICES = ( (ACTION_CREATE, 'created'), + (ACTION_BULK_CREATE, 'bulk created'), (ACTION_IMPORT, 'imported'), (ACTION_EDIT, 'modified'), (ACTION_BULK_EDIT, 'bulk edited'), (ACTION_DELETE, 'deleted'), - (ACTION_BULK_DELETE, 'bulk deleted') + (ACTION_BULK_DELETE, 'bulk deleted'), ) @@ -328,6 +330,9 @@ class UserActionManager(models.Manager): def log_import(self, user, content_type, message=''): self.log_bulk_action(user, content_type, ACTION_IMPORT, message) + def log_bulk_create(self, user, content_type, message=''): + self.log_bulk_action(user, content_type, ACTION_BULK_CREATE, message) + def log_bulk_edit(self, user, content_type, message=''): self.log_bulk_action(user, content_type, ACTION_BULK_EDIT, message) @@ -358,7 +363,7 @@ class UserAction(models.Model): return u'{} {} {}'.format(self.user, self.get_action_display(), self.content_type) def icon(self): - if self.action in [ACTION_CREATE, ACTION_IMPORT]: + if self.action in [ACTION_CREATE, ACTION_BULK_CREATE, ACTION_IMPORT]: return mark_safe('') elif self.action in [ACTION_EDIT, ACTION_BULK_EDIT]: return mark_safe('') diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index bcbb80e8b..864909878 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -1,6 +1,7 @@ from django_tables2 import RequestConfig import netaddr +from django.conf import settings from django.contrib.auth.decorators import permission_required from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib import messages @@ -295,7 +296,12 @@ def aggregate(request, pk): prefix_table = tables.PrefixTable(child_prefixes) if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'): prefix_table.base_columns['pk'].visible = True - RequestConfig(request, paginate={'klass': EnhancedPaginator}).configure(prefix_table) + + paginate = { + 'klass': EnhancedPaginator, + 'per_page': request.GET.get('per_page', settings.PAGINATE_COUNT) + } + RequestConfig(request, paginate).configure(prefix_table) # Compile permissions list for rendering the object table permissions = { @@ -427,7 +433,12 @@ def prefix(request, pk): child_prefix_table = tables.PrefixTable(child_prefixes) if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'): child_prefix_table.base_columns['pk'].visible = True - RequestConfig(request, paginate={'klass': EnhancedPaginator}).configure(child_prefix_table) + + paginate = { + 'klass': EnhancedPaginator, + 'per_page': request.GET.get('per_page', settings.PAGINATE_COUNT) + } + RequestConfig(request, paginate).configure(child_prefix_table) # Compile permissions list for rendering the object table permissions = { @@ -500,7 +511,12 @@ def prefix_ipaddresses(request, pk): ip_table = tables.IPAddressTable(ipaddresses) if request.user.has_perm('ipam.change_ipaddress') or request.user.has_perm('ipam.delete_ipaddress'): ip_table.base_columns['pk'].visible = True - RequestConfig(request, paginate={'klass': EnhancedPaginator}).configure(ip_table) + + paginate = { + 'klass': EnhancedPaginator, + 'per_page': request.GET.get('per_page', settings.PAGINATE_COUNT) + } + RequestConfig(request, paginate).configure(ip_table) # Compile permissions list for rendering the object table permissions = { diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index ae81d2689..e34d28f6c 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -12,7 +12,7 @@ except ImportError: "the documentation.") -VERSION = '1.9.3' +VERSION = '1.9.4' # Import local configuration for setting in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY']: diff --git a/netbox/templates/_base.html b/netbox/templates/_base.html index 0ebc4f5b4..ba90f0106 100644 --- a/netbox/templates/_base.html +++ b/netbox/templates/_base.html @@ -28,7 +28,7 @@
+ {% if form.custom_fields %}