Browse Source

Merge branch 'develop' into develop-2.1

Conflicts:
	netbox/ipam/models.py
	netbox/netbox/settings.py
	netbox/templates/dcim/inc/interface.html
Jeremy Stretch 7 years ago
parent
commit
5b43a108bc

+ 1 - 1
docs/data-model/extras.md

@@ -119,7 +119,7 @@ Each line of the **device patterns** field represents a hierarchical layer withi
 ```
 core-switch-[abcd]
 dist-switch\d
-access-switch\d+,oob-switch\d+
+access-switch\d+;oob-switch\d+
 ```
 
 Note that you can combine multiple regexes onto one line using semicolons. The order in which regexes are listed on a line is significant: devices matching the first regex will be rendered first, and subsequent groups will be rendered to the right of those.

+ 4 - 0
netbox/extras/api/customfields.py

@@ -49,6 +49,10 @@ class CustomFieldsSerializer(serializers.BaseSerializer):
 
             # Validate selected choice
             if cf.type == CF_TYPE_SELECT:
+                try:
+                    value = int(value)
+                except ValueError:
+                    raise ValidationError("{}: Choice selections must be passed as integers.".format(field_name))
                 valid_choices = [c.pk for c in cf.choices.all()]
                 if value not in valid_choices:
                     raise ValidationError("Invalid choice for field {}: {}".format(field_name, value))

+ 1 - 1
netbox/extras/models.py

@@ -332,7 +332,7 @@ def image_upload(instance, filename):
     path = 'image-attachments/'
 
     # Rename the file to the provided name, if any. Attempt to preserve the file extension.
-    extension = filename.rsplit('.')[-1]
+    extension = filename.rsplit('.')[-1].lower()
     if instance.name and extension in ['bmp', 'gif', 'jpeg', 'jpg', 'png']:
         filename = '.'.join([instance.name, extension])
     elif instance.name:

+ 1 - 1
netbox/extras/views.py

@@ -25,7 +25,7 @@ class ImageAttachmentEditView(PermissionRequiredMixin, ObjectEditView):
 
 
 class ImageAttachmentDeleteView(PermissionRequiredMixin, ObjectDeleteView):
-    permission_required = 'dcim.delete_imageattachment'
+    permission_required = 'extras.delete_imageattachment'
     model = ImageAttachment
 
     def get_return_url(self, request, imageattachment):

+ 12 - 5
netbox/ipam/forms.py

@@ -646,16 +646,23 @@ class IPAddressCSVForm(forms.ModelForm):
 
         # Set interface
         if self.cleaned_data['device'] and self.cleaned_data['interface_name']:
-            self.instance.interface = Interface.objects.get(device=self.cleaned_data['device'],
-                                                            name=self.cleaned_data['interface_name'])
+            self.instance.interface = Interface.objects.get(
+                device=self.cleaned_data['device'],
+                name=self.cleaned_data['interface_name']
+            )
+
+        ipaddress = super(IPAddressCSVForm, self).save(*args, **kwargs)
+
         # Set as primary for device
         if self.cleaned_data['is_primary']:
+            device = self.cleaned_data['device']
             if self.instance.address.version == 4:
-                self.instance.primary_ip4_for = self.cleaned_data['device']
+                device.primary_ip4 = ipaddress
             elif self.instance.address.version == 6:
-                self.instance.primary_ip6_for = self.cleaned_data['device']
+                device.primary_ip6 = ipaddress
+            device.save()
 
-        return super(IPAddressCSVForm, self).save(*args, **kwargs)
+        return ipaddress
 
 
 class IPAddressBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):

+ 17 - 13
netbox/ipam/models.py

@@ -158,13 +158,9 @@ class Aggregate(CreatedUpdatedModel, CustomFieldModel):
         """
         Determine the prefix utilization of the aggregate and return it as a percentage.
         """
-        child_prefixes = Prefix.objects.filter(prefix__net_contained_or_equal=str(self.prefix))
-        # Remove overlapping prefixes from list of children
-        networks = netaddr.cidr_merge([c.prefix for c in child_prefixes])
-        children_size = float(0)
-        for p in networks:
-            children_size += p.size
-        return int(children_size / self.prefix.size * 100)
+        queryset = Prefix.objects.filter(prefix__net_contained_or_equal=str(self.prefix))
+        child_prefixes = netaddr.IPSet([p.prefix for p in queryset])
+        return int(float(child_prefixes.size) / self.prefix.size * 100)
 
 
 @python_2_unicode_compatible
@@ -345,13 +341,21 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel):
 
     def get_utilization(self):
         """
-        Determine the utilization of the prefix and return it as a percentage.
+        Determine the utilization of the prefix and return it as a percentage. For Prefixes with a status of
+        "container", calculate utilization based on child prefixes. For all others, count child IP addresses.
         """
-        child_count = self.get_child_ips().count()
-        prefix_size = self.prefix.size
-        if self.family == 4 and self.prefix.prefixlen < 31 and not self.is_pool:
-            prefix_size -= 2
-        return int(float(child_count) / prefix_size * 100)
+        if self.status == PREFIX_STATUS_CONTAINER:
+            queryset = Prefix.objects.filter(prefix__net_contained=str(self.prefix), vrf=self.vrf)
+            child_prefixes = netaddr.IPSet([p.prefix for p in queryset])
+            return int(float(child_prefixes.size) / self.prefix.size * 100)
+        else:
+            child_count = IPAddress.objects.filter(
+                address__net_contained_or_equal=str(self.prefix), vrf=self.vrf
+            ).count()
+            prefix_size = self.prefix.size
+            if self.family == 4 and self.prefix.prefixlen < 31 and not self.is_pool:
+                prefix_size -= 2
+            return int(float(child_count) / prefix_size * 100)
 
     @property
     def new_subnet(self):

+ 1 - 1
netbox/ipam/tables.py

@@ -241,7 +241,7 @@ class PrefixTable(BaseTable):
     prefix = tables.TemplateColumn(PREFIX_LINK, attrs={'th': {'style': 'padding-left: 17px'}})
     status = tables.TemplateColumn(STATUS_LABEL)
     vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF')
-    get_utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False, verbose_name='IP Usage')
+    get_utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False, verbose_name='Utilization')
     tenant = tables.TemplateColumn(TENANT_LINK)
     site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
     vlan = tables.LinkColumn('ipam:vlan', args=[Accessor('vlan.pk')], verbose_name='VLAN')

+ 0 - 13
netbox/ipam/views.py

@@ -665,19 +665,6 @@ class IPAddressBulkImportView(PermissionRequiredMixin, BulkImportView):
     table = tables.IPAddressTable
     default_return_url = 'ipam:ipaddress_list'
 
-    def save_obj(self, obj):
-        obj.save()
-
-        # Update primary IP for device if needed. The Device must be updated directly in the database; otherwise we risk
-        # overwriting a previous IP assignment from the same import (see #861).
-        try:
-            if obj.family == 4 and obj.primary_ip4_for:
-                Device.objects.filter(pk=obj.primary_ip4_for.pk).update(primary_ip4=obj)
-            elif obj.family == 6 and obj.primary_ip6_for:
-                Device.objects.filter(pk=obj.primary_ip6_for.pk).update(primary_ip6=obj)
-        except Device.DoesNotExist:
-            pass
-
 
 class IPAddressBulkEditView(PermissionRequiredMixin, BulkEditView):
     permission_required = 'ipam.change_ipaddress'

+ 3 - 3
netbox/templates/dcim/device.html

@@ -204,7 +204,7 @@
                     None
                 </div>
             {% endif %}
-            {% if perms.dcim.add_service %}
+            {% if perms.ipam.add_service %}
                 <div class="panel-footer text-right">
                     <a href="{% url 'dcim:service_assign' device=device.pk %}" class="btn btn-xs btn-primary">
                         <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Assign service
@@ -572,7 +572,7 @@ function toggleConnection(elem, api_url) {
             success: function() {
                 elem.parents('tr').removeClass('success').addClass('info');
                 elem.removeClass('connected btn-warning').addClass('btn-success');
-                elem.attr('title', 'Mark connected');
+                elem.attr('title', 'Mark installed');
                 elem.children('i').removeClass('glyphicon glyphicon-ban-circle').addClass('fa fa-plug')
             }
         });
@@ -591,7 +591,7 @@ function toggleConnection(elem, api_url) {
             success: function() {
                 elem.parents('tr').removeClass('info').addClass('success');
                 elem.removeClass('btn-success').addClass('connected btn-warning');
-                elem.attr('title', 'Mark disconnected');
+                elem.attr('title', 'Mark planned');
                 elem.children('i').removeClass('fa fa-plug').addClass('glyphicon glyphicon-ban-circle')
             }
         });

+ 12 - 12
netbox/templates/dcim/inc/consoleport.html

@@ -18,24 +18,24 @@
         {% if perms.dcim.change_consoleport %}
             {% if cp.cs_port %}
                 {% if cp.connection_status %}
-                    <a href="#" class="btn btn-warning btn-xs consoleport-toggle connected" data="{{ cp.pk }}">
-                        <i class="glyphicon glyphicon-ban-circle" aria-hidden="true" title="Mark planned"></i>
+                    <a href="#" class="btn btn-warning btn-xs consoleport-toggle connected" title="Mark planned" data="{{ cp.pk }}">
+                        <i class="glyphicon glyphicon-ban-circle" aria-hidden="true"></i>
                     </a>
                 {% else %}
-                    <a href="#" class="btn btn-success btn-xs consoleport-toggle" data="{{ cp.pk }}">
-                        <i class="fa fa-plug" aria-hidden="true" title="Mark connected"></i>
+                    <a href="#" class="btn btn-success btn-xs consoleport-toggle" title="Mark installed" data="{{ cp.pk }}">
+                        <i class="fa fa-plug" aria-hidden="true"></i>
                     </a>
                 {% endif %}
-                <a href="{% url 'dcim:consoleport_disconnect' pk=cp.pk %}" class="btn btn-danger btn-xs">
-                    <i class="glyphicon glyphicon-resize-full" aria-hidden="true" title="Delete connection"></i>
+                <a href="{% url 'dcim:consoleport_disconnect' pk=cp.pk %}" title="Delete connection" class="btn btn-danger btn-xs">
+                    <i class="glyphicon glyphicon-resize-full" aria-hidden="true"></i>
                 </a>
             {% else %}
-                <a href="{% url 'dcim:consoleport_connect' pk=cp.pk %}" class="btn btn-success btn-xs">
-                    <i class="glyphicon glyphicon-resize-small" aria-hidden="true" title="Connect"></i>
+                <a href="{% url 'dcim:consoleport_connect' pk=cp.pk %}" title="Connect" class="btn btn-success btn-xs">
+                    <i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i>
                 </a>
             {% endif %}
-            <a href="{% url 'dcim:consoleport_edit' pk=cp.pk %}" class="btn btn-info btn-xs">
-                <i class="glyphicon glyphicon-pencil" aria-hidden="true" title="Edit port"></i>
+            <a href="{% url 'dcim:consoleport_edit' pk=cp.pk %}" title="Edit port" class="btn btn-info btn-xs">
+                <i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
             </a>
         {% endif %}
         {% if perms.dcim.delete_consoleport %}
@@ -44,8 +44,8 @@
                     <i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
                 </button>
             {% else %}
-                <a href="{% url 'dcim:consoleport_delete' pk=cp.pk %}" class="btn btn-danger btn-xs">
-                    <i class="glyphicon glyphicon-trash" aria-hidden="true" title="Delete port"></i>
+                <a href="{% url 'dcim:consoleport_delete' pk=cp.pk %}" title="Delete port" class="btn btn-danger btn-xs">
+                    <i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
                 </a>
             {% endif %}
         {% endif %}

+ 12 - 12
netbox/templates/dcim/inc/consoleserverport.html

@@ -24,24 +24,24 @@
         {% if perms.dcim.change_consoleserverport %}
             {% if csp.connected_console %}
                 {% if csp.connected_console.connection_status %}
-                    <a href="#" class="btn btn-warning btn-xs consoleport-toggle connected" data="{{ csp.connected_console.pk }}">
-                        <i class="glyphicon glyphicon-ban-circle" aria-hidden="true" title="Mark planned"></i>
+                    <a href="#" class="btn btn-warning btn-xs consoleport-toggle connected" title="Mark planned" data="{{ csp.connected_console.pk }}">
+                        <i class="glyphicon glyphicon-ban-circle" aria-hidden="true"></i>
                     </a>
                 {% else %}
-                    <a href="#" class="btn btn-success btn-xs consoleport-toggle" data="{{ csp.connected_console.pk }}">
-                        <i class="fa fa-plug" aria-hidden="true" title="Mark connected"></i>
+                    <a href="#" class="btn btn-success btn-xs consoleport-toggle" title="Mark installed" data="{{ csp.connected_console.pk }}">
+                        <i class="fa fa-plug" aria-hidden="true"></i>
                     </a>
                 {% endif %}
-                <a href="{% url 'dcim:consoleserverport_disconnect' pk=csp.pk %}" class="btn btn-danger btn-xs">
-                    <i class="glyphicon glyphicon-resize-full" aria-hidden="true" title="Delete connection"></i>
+                <a href="{% url 'dcim:consoleserverport_disconnect' pk=csp.pk %}" title="Delete connection" class="btn btn-danger btn-xs">
+                    <i class="glyphicon glyphicon-resize-full" aria-hidden="true"></i>
                 </a>
             {% else %}
-                <a href="{% url 'dcim:consoleserverport_connect' pk=csp.pk %}" class="btn btn-success btn-xs">
-                    <i class="glyphicon glyphicon-resize-small" aria-hidden="true" title="Connect"></i>
+                <a href="{% url 'dcim:consoleserverport_connect' pk=csp.pk %}" title="Connect" class="btn btn-success btn-xs">
+                    <i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i>
                 </a>
             {% endif %}
-            <a href="{% url 'dcim:consoleserverport_edit' pk=csp.pk %}" class="btn btn-info btn-xs">
-                <i class="glyphicon glyphicon-pencil" aria-hidden="true" title="Edit port"></i>
+            <a href="{% url 'dcim:consoleserverport_edit' pk=csp.pk %}" title="Edit port" class="btn btn-info btn-xs">
+                <i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
             </a>
         {% endif %}
         {% if perms.dcim.delete_consoleserverport %}
@@ -50,8 +50,8 @@
                     <i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
                 </button>
             {% else %}
-                <a href="{% url 'dcim:consoleserverport_delete' pk=csp.pk %}" class="btn btn-danger btn-xs">
-                    <i class="glyphicon glyphicon-trash" aria-hidden="true" title="Delete port"></i>
+                <a href="{% url 'dcim:consoleserverport_delete' pk=csp.pk %}" title="Delete port" class="btn btn-danger btn-xs">
+                    <i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
                 </a>
             {% endif %}
         {% endif %}

+ 1 - 1
netbox/templates/dcim/inc/device_header.html

@@ -45,7 +45,7 @@
 <ul class="nav nav-tabs" style="margin-bottom: 20px">
     <li role="presentation"{% if active_tab == 'info' %} class="active"{% endif %}><a href="{% url 'dcim:device' pk=device.pk %}">Info</a></li>
     <li role="presentation"{% if active_tab == 'inventory' %} class="active"{% endif %}><a href="{% url 'dcim:device_inventory' pk=device.pk %}">Inventory</a></li>
-    {% if device.status %}
+    {% if device.status == 1 and device.platform.rpc_client and device.primary_ip %}
         <li role="presentation"{% if active_tab == 'lldp-neighbors' %} class="active"{% endif %}><a href="{% url 'dcim:device_lldp_neighbors' pk=device.pk %}">LLDP Neighbors</a></li>
     {% endif %}
 </ul>

+ 2 - 2
netbox/templates/dcim/inc/interface.html

@@ -1,4 +1,4 @@
-<tr class="interface{% if not iface.enabled %} danger{% elif iface.connection and not iface.connection.connection_status %} info{% endif %}">
+<tr class="interface{% if not iface.enabled %} danger{% elif iface.connection and iface.connection.connection_status %} success{% elif iface.connection and not iface.connection.connection_status %} info{% endif %}">
     {% if selectable and perms.dcim.change_interface or perms.dcim.delete_interface %}
         <td class="pk">
             <input name="pk" type="checkbox" value="{{ iface.pk }}" />
@@ -76,7 +76,7 @@
                             <i class="glyphicon glyphicon-ban-circle" aria-hidden="true"></i>
                         </a>
                     {% else %}
-                        <a href="#" class="btn btn-success btn-xs interface-toggle" data="{{ iface.connection.pk }}" title="Mark connected">
+                        <a href="#" class="btn btn-success btn-xs interface-toggle" data="{{ iface.connection.pk }}" title="Mark installed">
                             <i class="fa fa-plug" aria-hidden="true"></i>
                         </a>
                     {% endif %}

+ 12 - 12
netbox/templates/dcim/inc/poweroutlet.html

@@ -24,24 +24,24 @@
         {% if perms.dcim.change_poweroutlet %}
             {% if po.connected_port %}
                 {% if po.connected_port.connection_status %}
-                    <a href="#" class="btn btn-warning btn-xs powerport-toggle connected" data="{{ po.connected_port.pk }}">
-                        <i class="glyphicon glyphicon-ban-circle" aria-hidden="true" title="Mark planned"></i>
+                    <a href="#" class="btn btn-warning btn-xs powerport-toggle connected" title="Mark planned" data="{{ po.connected_port.pk }}">
+                        <i class="glyphicon glyphicon-ban-circle" aria-hidden="true"></i>
                     </a>
                 {% else %}
-                    <a href="#" class="btn btn-success btn-xs consoleport-toggle" data="{{ po.connected_port.pk }}">
-                        <i class="fa fa-plug" aria-hidden="true" title="Mark connected"></i>
+                    <a href="#" class="btn btn-success btn-xs consoleport-toggle" title="Mark installed" data="{{ po.connected_port.pk }}">
+                        <i class="fa fa-plug" aria-hidden="true"></i>
                     </a>
                 {% endif %}
-                <a href="{% url 'dcim:poweroutlet_disconnect' pk=po.pk %}" class="btn btn-danger btn-xs">
-                    <i class="glyphicon glyphicon-resize-full" aria-hidden="true" title="Delete connection"></i>
+                <a href="{% url 'dcim:poweroutlet_disconnect' pk=po.pk %}" title="Delete connection" class="btn btn-danger btn-xs">
+                    <i class="glyphicon glyphicon-resize-full" aria-hidden="true"></i>
                 </a>
             {% else %}
-                <a href="{% url 'dcim:poweroutlet_connect' pk=po.pk %}" class="btn btn-success btn-xs">
-                    <i class="glyphicon glyphicon-resize-small" aria-hidden="true" title="Connect"></i>
+                <a href="{% url 'dcim:poweroutlet_connect' pk=po.pk %}" title="Connect" class="btn btn-success btn-xs">
+                    <i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i>
                 </a>
             {% endif %}
-            <a href="{% url 'dcim:poweroutlet_edit' pk=po.pk %}" class="btn btn-info btn-xs">
-                <i class="glyphicon glyphicon-pencil" aria-hidden="true" title="Edit outlet"></i>
+            <a href="{% url 'dcim:poweroutlet_edit' pk=po.pk %}" title="Edit outlet" class="btn btn-info btn-xs">
+                <i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
             </a>
         {% endif %}
         {% if perms.dcim.delete_poweroutlet %}
@@ -50,8 +50,8 @@
                     <i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
                 </button>
             {% else %}
-                <a href="{% url 'dcim:poweroutlet_delete' pk=po.pk %}" class="btn btn-danger btn-xs">
-                    <i class="glyphicon glyphicon-trash" aria-hidden="true" title="Delete outlet"></i>
+                <a href="{% url 'dcim:poweroutlet_delete' pk=po.pk %}" title="Delete outlet" class="btn btn-danger btn-xs">
+                    <i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
                 </a>
             {% endif %}
         {% endif %}

+ 12 - 12
netbox/templates/dcim/inc/powerport.html

@@ -18,24 +18,24 @@
         {% if perms.dcim.change_powerport %}
             {% if pp.power_outlet %}
                 {% if pp.connection_status %}
-                    <a href="#" class="btn btn-warning btn-xs powerport-toggle connected" data="{{ pp.pk }}">
-                        <i class="glyphicon glyphicon-ban-circle" aria-hidden="true" title="Mark planned"></i>
+                    <a href="#" class="btn btn-warning btn-xs powerport-toggle connected" title="Mark planned" data="{{ pp.pk }}">
+                        <i class="glyphicon glyphicon-ban-circle" aria-hidden="true"></i>
                     </a>
                 {% else %}
-                    <a href="#" class="btn btn-success btn-xs powerport-toggle" data="{{ pp.pk }}">
-                        <i class="fa fa-plug" aria-hidden="true" title="Mark connected"></i>
+                    <a href="#" class="btn btn-success btn-xs powerport-toggle" title="Mark installed" data="{{ pp.pk }}">
+                        <i class="fa fa-plug" aria-hidden="true"></i>
                     </a>
                 {% endif %}
-            <a href="{% url 'dcim:powerport_disconnect' pk=pp.pk %}" class="btn btn-danger btn-xs">
-                <i class="glyphicon glyphicon-resize-full" aria-hidden="true" title="Delete connection"></i>
+            <a href="{% url 'dcim:powerport_disconnect' pk=pp.pk %}" title="Delete connection" class="btn btn-danger btn-xs">
+                <i class="glyphicon glyphicon-resize-full" aria-hidden="true"></i>
             </a>
             {% else %}
-                <a href="{% url 'dcim:powerport_connect' pk=pp.pk %}" class="btn btn-success btn-xs">
-                    <i class="glyphicon glyphicon-resize-small" aria-hidden="true" title="Connect"></i>
+                <a href="{% url 'dcim:powerport_connect' pk=pp.pk %}" title="Connect" class="btn btn-success btn-xs">
+                    <i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i>
                 </a>
             {% endif %}
-            <a href="{% url 'dcim:powerport_edit' pk=pp.pk %}" class="btn btn-info btn-xs">
-                <i class="glyphicon glyphicon-pencil" aria-hidden="true" title="Edit port"></i>
+            <a href="{% url 'dcim:powerport_edit' pk=pp.pk %}" title="Edit port" class="btn btn-info btn-xs">
+                <i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
             </a>
         {% endif %}
         {% if perms.dcim.delete_powerport %}
@@ -44,8 +44,8 @@
                     <i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
                 </button>
             {% else %}
-                <a href="{% url 'dcim:powerport_delete' pk=pp.pk %}" class="btn btn-danger btn-xs">
-                    <i class="glyphicon glyphicon-trash" aria-hidden="true" title="Delete port"></i>
+                <a href="{% url 'dcim:powerport_delete' pk=pp.pk %}" title="Delete port" class="btn btn-danger btn-xs">
+                    <i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
                 </a>
             {% endif %}
         {% endif %}

+ 6 - 0
netbox/templates/users/userkey.html

@@ -19,6 +19,12 @@
             {% endif %}
         </h4>
         {% include 'inc/created_updated.html' with obj=userkey %}
+        {% if not userkey.is_active %}
+            <div class="alert alert-warning" role="alert">
+                <i class="fa fa-warning"></i>
+                Your user key is inactive. Ask an administrator to enable it for you.
+            </div>
+        {% endif %}
         <pre>{{ userkey.public_key }}</pre>
         <hr />
         {% if userkey.session_key %}

+ 6 - 3
netbox/utilities/forms.py

@@ -472,9 +472,6 @@ class ChainedFieldsMixin(forms.BaseForm):
     def __init__(self, *args, **kwargs):
         super(ChainedFieldsMixin, self).__init__(*args, **kwargs)
 
-        # if self.is_bound:
-        #     assert False, self.data
-
         for field_name, field in self.fields.items():
 
             if isinstance(field, ChainedModelChoiceField):
@@ -492,6 +489,12 @@ class ChainedFieldsMixin(forms.BaseForm):
 
                 if filters_dict:
                     field.queryset = field.queryset.filter(**filters_dict)
+                elif not self.is_bound and getattr(self, 'instance', None) and hasattr(self.instance, field_name):
+                    obj = getattr(self.instance, field_name)
+                    if obj is not None:
+                        field.queryset = field.queryset.filter(pk=obj.pk)
+                    else:
+                        field.queryset = field.queryset.none()
                 elif not self.is_bound:
                     field.queryset = field.queryset.none()
 

+ 1 - 1
netbox/utilities/views.py

@@ -234,7 +234,7 @@ class ObjectDeleteView(GetReturnURLMixin, View):
     """
     Delete a single object.
 
-    model: The model of the object being edited
+    model: The model of the object being deleted
     template_name: The name of the template
     default_return_url: Name of the URL to which the user is redirected after deleting the object
     """