From efb95937fc9274ab43a95ea22c6c35ff984460f8 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 6 Dec 2016 15:32:11 -0500 Subject: [PATCH 1/8] Reverting GitHub test --- netbox/tempfile | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 netbox/tempfile diff --git a/netbox/tempfile b/netbox/tempfile deleted file mode 100644 index e69de29bb..000000000 From 4a9b4c5387aace8eb72cfbda3aad76e5a3896ef4 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 7 Dec 2016 14:00:52 -0500 Subject: [PATCH 2/8] Fixes #732: Allow custom select field values to be deselected if the field is not required --- netbox/extras/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/extras/forms.py b/netbox/extras/forms.py index d7a37dacd..9d738219d 100644 --- a/netbox/extras/forms.py +++ b/netbox/extras/forms.py @@ -49,7 +49,7 @@ def get_custom_fields_for_model(content_type, filterable_only=False, bulk_edit=F # Select elif cf.type == CF_TYPE_SELECT: choices = [(cfc.pk, cfc) for cfc in cf.choices.all()] - if bulk_edit or filterable_only: + if not cf.required or bulk_edit or filterable_only: choices = [(None, '---------')] + choices field = forms.TypedChoiceField(choices=choices, coerce=int, required=cf.required) From fca812928e901739714ea2dcc9c0335e9b8d96a3 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 7 Dec 2016 15:14:22 -0500 Subject: [PATCH 3/8] #724: Exempt API views from LoginRequiredMiddleware to enable basic HTTP authentication when LOGIN_REQUIRED is true --- netbox/netbox/settings.py | 2 ++ netbox/utilities/middleware.py | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 34d856f2e..b479420bd 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -185,6 +185,8 @@ SECRETS_MIN_PUBKEY_SIZE = 2048 REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',) } +if LOGIN_REQUIRED: + REST_FRAMEWORK['DEFAULT_PERMISSION_CLASSES'] = ('rest_framework.permissions.IsAuthenticated',) # Swagger settings (API docs) SWAGGER_SETTINGS = { diff --git a/netbox/utilities/middleware.py b/netbox/utilities/middleware.py index e37c1fcca..2bd25b00c 100644 --- a/netbox/utilities/middleware.py +++ b/netbox/utilities/middleware.py @@ -2,6 +2,7 @@ from django.http import HttpResponseRedirect from django.conf import settings +BASE_PATH = getattr(settings, 'BASE_PATH', False) LOGIN_REQUIRED = getattr(settings, 'LOGIN_REQUIRED', False) @@ -11,5 +12,8 @@ class LoginRequiredMiddleware: """ def process_request(self, request): if LOGIN_REQUIRED and not request.user.is_authenticated(): - if request.path_info != settings.LOGIN_URL: + # Redirect unauthenticated requests to the login page. API requests are exempt from redirection as the API + # performs its own authentication. + api_path = '/{}api/'.format(BASE_PATH) + if not request.path_info.startswith(api_path) and request.path_info != settings.LOGIN_URL: return HttpResponseRedirect('{}?next={}'.format(settings.LOGIN_URL, request.path_info)) From b4940a64beabc4d4b698a46a632f0818c1d3cd96 Mon Sep 17 00:00:00 2001 From: stanley karunditu Date: Wed, 7 Dec 2016 15:04:01 -0500 Subject: [PATCH 4/8] FIX: filtering devices fails because mac address filter is a required field --- netbox/dcim/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 23da437a7..cb6ed261a 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -612,7 +612,7 @@ class DeviceFilterForm(BootstrapMixin, CustomFieldFilterForm): platform = FilterChoiceField(queryset=Platform.objects.annotate(filter_count=Count('devices')), to_field_name='slug', null_option=(0, 'None')) status = forms.NullBooleanField(required=False, widget=forms.Select(choices=FORM_STATUS_CHOICES)) - mac_address = forms.CharField(label='MAC address') + mac_address = forms.CharField(label='MAC address', required=False) # From 3a6d7a1f7faf5d16f3e23be789deb41a308d2d2e Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 7 Dec 2016 15:53:19 -0500 Subject: [PATCH 5/8] #733: Fixed MAC address device filter --- netbox/dcim/filters.py | 5 ++++- netbox/dcim/forms.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 69bccd253..4cf53c303 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -260,8 +260,11 @@ class DeviceFilter(CustomFieldFilterSet, django_filters.FilterSet): ).distinct() def _mac_address(self, queryset, value): + value = value.strip() + if not value: + return queryset try: - return queryset.filter(interfaces__mac_address=value.strip()).distinct() + return queryset.filter(interfaces__mac_address=value).distinct() except AddrFormatError: return queryset.none() diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index cb6ed261a..961d22440 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -612,7 +612,7 @@ class DeviceFilterForm(BootstrapMixin, CustomFieldFilterForm): platform = FilterChoiceField(queryset=Platform.objects.annotate(filter_count=Count('devices')), to_field_name='slug', null_option=(0, 'None')) status = forms.NullBooleanField(required=False, widget=forms.Select(choices=FORM_STATUS_CHOICES)) - mac_address = forms.CharField(label='MAC address', required=False) + mac_address = forms.CharField(required=False, label='MAC address') # From d5095362d7687111076800eaaf1b6409842965de Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 8 Dec 2016 09:59:21 -0500 Subject: [PATCH 6/8] Fixes #734: Corrected display of device type when editing a device --- netbox/dcim/admin.py | 6 +++++- netbox/dcim/models.py | 6 +++++- netbox/dcim/tables.py | 6 ++++-- netbox/templates/dcim/device.html | 4 ++-- netbox/templates/dcim/device_bulk_add_component.html | 2 +- netbox/templates/dcim/device_bulk_edit.html | 2 +- netbox/templates/dcim/device_inventory.html | 2 +- netbox/templates/dcim/devicetype.html | 4 ++-- netbox/templates/dcim/inc/_devicebay.html | 2 +- netbox/templates/dcim/inc/_rack_elevation.html | 2 +- netbox/templates/dcim/rack.html | 10 ++++++++-- 11 files changed, 31 insertions(+), 15 deletions(-) diff --git a/netbox/dcim/admin.py b/netbox/dcim/admin.py index 9fd16a87d..8828b52c4 100644 --- a/netbox/dcim/admin.py +++ b/netbox/dcim/admin.py @@ -183,10 +183,14 @@ class DeviceAdmin(admin.ModelAdmin): DeviceBayAdmin, ModuleAdmin, ] - list_display = ['display_name', 'device_type', 'device_role', 'primary_ip', 'rack', 'position', 'asset_tag', + list_display = ['display_name', 'device_type_full_name', 'device_role', 'primary_ip', 'rack', 'position', 'asset_tag', 'serial'] list_filter = ['device_role'] def get_queryset(self, request): qs = super(DeviceAdmin, self).get_queryset(request) return qs.select_related('device_type__manufacturer', 'device_role', 'primary_ip4', 'primary_ip6', 'rack') + + def device_type_full_name(self, obj): + return obj.device_type.full_name + device_type_full_name.short_description = 'Device type' diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index e8967b0c0..a87b778d7 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -561,7 +561,7 @@ class DeviceType(models.Model): ] def __unicode__(self): - return u'{} {}'.format(self.manufacturer, self.model) + return self.model def __init__(self, *args, **kwargs): super(DeviceType, self).__init__(*args, **kwargs) @@ -617,6 +617,10 @@ class DeviceType(models.Model): 'u_height': "Child device types must be 0U." }) + @property + def full_name(self): + return u'{} {}'.format(self.manufacturer.name, self.model) + @property def is_parent_device(self): return bool(self.subdevice_role) diff --git a/netbox/dcim/tables.py b/netbox/dcim/tables.py index c81c24f82..94d359ac0 100644 --- a/netbox/dcim/tables.py +++ b/netbox/dcim/tables.py @@ -294,7 +294,8 @@ class PlatformTable(BaseTable): name = tables.LinkColumn(verbose_name='Name') device_count = tables.Column(verbose_name='Devices') slug = tables.Column(verbose_name='Slug') - actions = tables.TemplateColumn(template_code=PLATFORM_ACTIONS, attrs={'td': {'class': 'text-right'}}, verbose_name='') + actions = tables.TemplateColumn(template_code=PLATFORM_ACTIONS, attrs={'td': {'class': 'text-right'}}, + verbose_name='') class Meta(BaseTable.Meta): model = Platform @@ -313,7 +314,8 @@ class DeviceTable(BaseTable): site = tables.Column(accessor=Accessor('rack.site'), verbose_name='Site') rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')], verbose_name='Rack') device_role = tables.TemplateColumn(DEVICE_ROLE, verbose_name='Role') - device_type = tables.Column(verbose_name='Type') + device_type = tables.LinkColumn('dcim:devicetype', args=[Accessor('device_type.pk')], verbose_name='Type', + text=lambda record: record.device_type.full_name) primary_ip = tables.TemplateColumn(orderable=False, verbose_name='IP Address', template_code="{{ record.primary_ip.address.ip }}") diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 14d5b0869..785938970 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -56,7 +56,7 @@ Device Type - {{ device.device_type }} ({{ device.device_type.u_height }}U) + {{ device.device_type.full_name }} ({{ device.device_type.u_height }}U) @@ -293,7 +293,7 @@ Rack {{ rd.rack }} - {{ rd.device_type }} + {{ rd.device_type.full_name }} {% endfor %} diff --git a/netbox/templates/dcim/device_bulk_add_component.html b/netbox/templates/dcim/device_bulk_add_component.html index 60d42484c..2854954cd 100644 --- a/netbox/templates/dcim/device_bulk_add_component.html +++ b/netbox/templates/dcim/device_bulk_add_component.html @@ -24,7 +24,7 @@ {% for device in selected_devices %} {{ device }} - {{ device.device_type }} + {{ device.device_type.full_name }} {{ device.device_role }} {% endfor %} diff --git a/netbox/templates/dcim/device_bulk_edit.html b/netbox/templates/dcim/device_bulk_edit.html index 21d72e238..69109828a 100644 --- a/netbox/templates/dcim/device_bulk_edit.html +++ b/netbox/templates/dcim/device_bulk_edit.html @@ -14,7 +14,7 @@ {% for device in selected_objects %} {{ device }} - {{ device.device_type }} + {{ device.device_type.full_name }} {{ device.device_role }} {{ device.tenant }} {{ device.serial }} diff --git a/netbox/templates/dcim/device_inventory.html b/netbox/templates/dcim/device_inventory.html index b43083e71..0642f2859 100644 --- a/netbox/templates/dcim/device_inventory.html +++ b/netbox/templates/dcim/device_inventory.html @@ -13,7 +13,7 @@ - + diff --git a/netbox/templates/dcim/devicetype.html b/netbox/templates/dcim/devicetype.html index 42cb30f99..0492bd2cc 100644 --- a/netbox/templates/dcim/devicetype.html +++ b/netbox/templates/dcim/devicetype.html @@ -2,7 +2,7 @@ {% load helpers %} {% load render_table from django_tables2 %} -{% block title %}{{ devicetype }}{% endblock %} +{% block title %}{{ devicetype.manufacturer }} {{ devicetype.model }}{% endblock %} {% block content %}
@@ -32,7 +32,7 @@
{% endif %} -

{{ devicetype }}

+

{{ devicetype.manufacturer }} {{ devicetype.model }}

diff --git a/netbox/templates/dcim/inc/_devicebay.html b/netbox/templates/dcim/inc/_devicebay.html index aaa9099c6..8996cd225 100644 --- a/netbox/templates/dcim/inc/_devicebay.html +++ b/netbox/templates/dcim/inc/_devicebay.html @@ -12,7 +12,7 @@ {{ devicebay.installed_device }}
{% else %} - - + + {% endfor %}
Model{{ device.device_type }}{{ device.device_type.full_name }}
Serial Number - {{ devicebay.installed_device.device_type }} + {{ devicebay.installed_device.device_type.full_name }} diff --git a/netbox/templates/dcim/inc/_rack_elevation.html b/netbox/templates/dcim/inc/_rack_elevation.html index 1ad8cdb57..0ffc6b7ad 100644 --- a/netbox/templates/dcim/inc/_rack_elevation.html +++ b/netbox/templates/dcim/inc/_rack_elevation.html @@ -24,7 +24,7 @@
  • {% ifequal u.device.face face_id %} + data-content="{{ u.device.device_role }}
    {{ u.device.device_type.full_name }} ({{ u.device.device_type.u_height }}U)"> {{ u.device.name|default:u.device.device_role }} {% if u.device.devicebay_count %} ({{ u.device.get_children.count }}/{{ u.device.devicebay_count }}) diff --git a/netbox/templates/dcim/rack.html b/netbox/templates/dcim/rack.html index af457a21d..f2bafe43b 100644 --- a/netbox/templates/dcim/rack.html +++ b/netbox/templates/dcim/rack.html @@ -153,8 +153,14 @@
    {{ device.name }}
  • {{ device.device_role }}{{ device.device_type }}{% if device.parent_bay %}{{ device.parent_bay }}{% endif %}{{ device.device_type.full_name }} + {% if device.parent_bay %} + {{ device.parent_bay }} + {% else %} + N/A + {% endif %} +
    From 5035a9567bf5ccb20373789041b4317c83293094 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 8 Dec 2016 12:20:45 -0500 Subject: [PATCH 7/8] Fixes #729: Corrected cancellation links when editing secondary objects --- netbox/circuits/views.py | 8 ++++---- netbox/dcim/views.py | 29 ++++++++++++++--------------- netbox/ipam/views.py | 23 +++++++++++------------ netbox/secrets/views.py | 4 ++-- netbox/tenancy/views.py | 6 +++--- netbox/utilities/views.py | 28 ++++++++++++---------------- 6 files changed, 46 insertions(+), 52 deletions(-) diff --git a/netbox/circuits/views.py b/netbox/circuits/views.py index 28c4d6844..292328d61 100644 --- a/netbox/circuits/views.py +++ b/netbox/circuits/views.py @@ -42,7 +42,7 @@ class ProviderEditView(PermissionRequiredMixin, ObjectEditView): model = Provider form_class = forms.ProviderForm template_name = 'circuits/provider_edit.html' - cancel_url = 'circuits:provider_list' + obj_list_url = 'circuits:provider_list' class ProviderDeleteView(PermissionRequiredMixin, ObjectDeleteView): @@ -88,8 +88,8 @@ class CircuitTypeEditView(PermissionRequiredMixin, ObjectEditView): permission_required = 'circuits.change_circuittype' model = CircuitType form_class = forms.CircuitTypeForm - success_url = 'circuits:circuittype_list' - cancel_url = 'circuits:circuittype_list' + obj_list_url = 'circuits:circuittype_list' + use_obj_view = False class CircuitTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): @@ -126,7 +126,7 @@ class CircuitEditView(PermissionRequiredMixin, ObjectEditView): form_class = forms.CircuitForm fields_initial = ['site'] template_name = 'circuits/circuit_edit.html' - cancel_url = 'circuits:circuit_list' + obj_list_url = 'circuits:circuit_list' class CircuitDeleteView(PermissionRequiredMixin, ObjectDeleteView): diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index d31670446..d7fc2a88b 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -8,7 +8,6 @@ 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 import transaction from django.db.models import Count from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, redirect, render @@ -99,7 +98,7 @@ class SiteEditView(PermissionRequiredMixin, ObjectEditView): model = Site form_class = forms.SiteForm template_name = 'dcim/site_edit.html' - cancel_url = 'dcim:site_list' + obj_list_url = 'dcim:site_list' class SiteDeleteView(PermissionRequiredMixin, ObjectDeleteView): @@ -141,8 +140,8 @@ class RackGroupEditView(PermissionRequiredMixin, ObjectEditView): permission_required = 'dcim.change_rackgroup' model = RackGroup form_class = forms.RackGroupForm - success_url = 'dcim:rackgroup_list' - cancel_url = 'dcim:rackgroup_list' + obj_list_url = 'dcim:rackgroup_list' + use_obj_view = False class RackGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): @@ -166,8 +165,8 @@ class RackRoleEditView(PermissionRequiredMixin, ObjectEditView): permission_required = 'dcim.change_rackrole' model = RackRole form_class = forms.RackRoleForm - success_url = 'dcim:rackrole_list' - cancel_url = 'dcim:rackrole_list' + obj_list_url = 'dcim:rackrole_list' + use_obj_view = False class RackRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): @@ -214,7 +213,7 @@ class RackEditView(PermissionRequiredMixin, ObjectEditView): model = Rack form_class = forms.RackForm template_name = 'dcim/rack_edit.html' - cancel_url = 'dcim:rack_list' + obj_list_url = 'dcim:rack_list' class RackDeleteView(PermissionRequiredMixin, ObjectDeleteView): @@ -260,8 +259,8 @@ class ManufacturerEditView(PermissionRequiredMixin, ObjectEditView): permission_required = 'dcim.change_manufacturer' model = Manufacturer form_class = forms.ManufacturerForm - success_url = 'dcim:manufacturer_list' - cancel_url = 'dcim:manufacturer_list' + obj_list_url = 'dcim:manufacturer_list' + use_obj_view = False class ManufacturerBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): @@ -332,7 +331,7 @@ class DeviceTypeEditView(PermissionRequiredMixin, ObjectEditView): permission_required = 'dcim.change_devicetype' model = DeviceType form_class = forms.DeviceTypeForm - cancel_url = 'dcim:devicetype_list' + obj_list_url = 'dcim:devicetype_list' class DeviceTypeDeleteView(PermissionRequiredMixin, ObjectDeleteView): @@ -497,8 +496,8 @@ class DeviceRoleEditView(PermissionRequiredMixin, ObjectEditView): permission_required = 'dcim.change_devicerole' model = DeviceRole form_class = forms.DeviceRoleForm - success_url = 'dcim:devicerole_list' - cancel_url = 'dcim:devicerole_list' + obj_list_url = 'dcim:devicerole_list' + use_obj_view = False class DeviceRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): @@ -522,8 +521,8 @@ class PlatformEditView(PermissionRequiredMixin, ObjectEditView): permission_required = 'dcim.change_platform' model = Platform form_class = forms.PlatformForm - success_url = 'dcim:platform_list' - cancel_url = 'dcim:platform_list' + obj_list_url = 'dcim:platform_list' + use_obj_view = False class PlatformBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): @@ -617,7 +616,7 @@ class DeviceEditView(PermissionRequiredMixin, ObjectEditView): form_class = forms.DeviceForm fields_initial = ['site', 'rack', 'position', 'face', 'device_bay'] template_name = 'dcim/device_edit.html' - cancel_url = 'dcim:device_list' + obj_list_url = 'dcim:device_list' class DeviceDeleteView(PermissionRequiredMixin, ObjectDeleteView): diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 0be5b225e..0ad11a38c 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -1,4 +1,3 @@ -from collections import OrderedDict from django_tables2 import RequestConfig import netaddr @@ -117,7 +116,7 @@ class VRFEditView(PermissionRequiredMixin, ObjectEditView): model = VRF form_class = forms.VRFForm template_name = 'ipam/vrf_edit.html' - cancel_url = 'ipam:vrf_list' + obj_list_url = 'ipam:vrf_list' class VRFDeleteView(PermissionRequiredMixin, ObjectDeleteView): @@ -241,8 +240,8 @@ class RIREditView(PermissionRequiredMixin, ObjectEditView): permission_required = 'ipam.change_rir' model = RIR form_class = forms.RIRForm - success_url = 'ipam:rir_list' - cancel_url = 'ipam:rir_list' + obj_list_url = 'ipam:rir_list' + use_obj_view = False class RIRBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): @@ -307,7 +306,7 @@ class AggregateEditView(PermissionRequiredMixin, ObjectEditView): model = Aggregate form_class = forms.AggregateForm template_name = 'ipam/aggregate_edit.html' - cancel_url = 'ipam:aggregate_list' + obj_list_url = 'ipam:aggregate_list' class AggregateDeleteView(PermissionRequiredMixin, ObjectDeleteView): @@ -353,8 +352,8 @@ class RoleEditView(PermissionRequiredMixin, ObjectEditView): permission_required = 'ipam.change_role' model = Role form_class = forms.RoleForm - success_url = 'ipam:role_list' - cancel_url = 'ipam:role_list' + obj_list_url = 'ipam:role_list' + use_obj_view = False class RoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): @@ -438,7 +437,7 @@ class PrefixEditView(PermissionRequiredMixin, ObjectEditView): form_class = forms.PrefixForm template_name = 'ipam/prefix_edit.html' fields_initial = ['vrf', 'tenant', 'site', 'prefix', 'vlan'] - cancel_url = 'ipam:prefix_list' + obj_list_url = 'ipam:prefix_list' class PrefixDeleteView(PermissionRequiredMixin, ObjectDeleteView): @@ -602,7 +601,7 @@ class IPAddressEditView(PermissionRequiredMixin, ObjectEditView): form_class = forms.IPAddressForm fields_initial = ['address', 'vrf'] template_name = 'ipam/ipaddress_edit.html' - cancel_url = 'ipam:ipaddress_list' + obj_list_url = 'ipam:ipaddress_list' class IPAddressDeleteView(PermissionRequiredMixin, ObjectDeleteView): @@ -665,8 +664,8 @@ class VLANGroupEditView(PermissionRequiredMixin, ObjectEditView): permission_required = 'ipam.change_vlangroup' model = VLANGroup form_class = forms.VLANGroupForm - success_url = 'ipam:vlangroup_list' - cancel_url = 'ipam:vlangroup_list' + obj_list_url = 'ipam:vlangroup_list' + use_obj_view = False class VLANGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): @@ -705,7 +704,7 @@ class VLANEditView(PermissionRequiredMixin, ObjectEditView): model = VLAN form_class = forms.VLANForm template_name = 'ipam/vlan_edit.html' - cancel_url = 'ipam:vlan_list' + obj_list_url = 'ipam:vlan_list' class VLANDeleteView(PermissionRequiredMixin, ObjectDeleteView): diff --git a/netbox/secrets/views.py b/netbox/secrets/views.py index a99af80b6..7880adfb2 100644 --- a/netbox/secrets/views.py +++ b/netbox/secrets/views.py @@ -30,8 +30,8 @@ class SecretRoleEditView(PermissionRequiredMixin, ObjectEditView): permission_required = 'secrets.change_secretrole' model = SecretRole form_class = forms.SecretRoleForm - success_url = 'secrets:secretrole_list' - cancel_url = 'secrets:secretrole_list' + obj_list_url = 'secrets:secretrole_list' + use_obj_view = False class SecretRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): diff --git a/netbox/tenancy/views.py b/netbox/tenancy/views.py index 1055fb9b3..821f6d7bf 100644 --- a/netbox/tenancy/views.py +++ b/netbox/tenancy/views.py @@ -28,8 +28,8 @@ class TenantGroupEditView(PermissionRequiredMixin, ObjectEditView): permission_required = 'tenancy.change_tenantgroup' model = TenantGroup form_class = forms.TenantGroupForm - success_url = 'tenancy:tenantgroup_list' - cancel_url = 'tenancy:tenantgroup_list' + obj_list_url = 'tenancy:tenantgroup_list' + use_obj_view = False class TenantGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): @@ -83,7 +83,7 @@ class TenantEditView(PermissionRequiredMixin, ObjectEditView): form_class = forms.TenantForm fields_initial = ['group'] template_name = 'tenancy/tenant_edit.html' - cancel_url = 'tenancy:tenant_list' + obj_list_url = 'tenancy:tenant_list' class TenantDeleteView(PermissionRequiredMixin, ObjectDeleteView): diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index 76d15c331..1b4493281 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -119,8 +119,8 @@ class ObjectEditView(View): form_class = None fields_initial = [] template_name = 'utilities/obj_edit.html' - success_url = None - cancel_url = None + obj_list_url = None + use_obj_view = True def get_object(self, kwargs): # Look up object by slug if one has been provided. Otherwise, use PK. @@ -129,12 +129,13 @@ class ObjectEditView(View): else: return get_object_or_404(self.model, pk=kwargs['pk']) - def get_cancel_url(self, obj): - if hasattr(obj, 'get_absolute_url'): - return obj.get_absolute_url() - if hasattr(obj, 'get_parent_url'): - return obj.get_parent_url() - return reverse(self.cancel_url) + def get_redirect_url(self, obj): + if obj and self.use_obj_view: + if hasattr(obj, 'get_absolute_url'): + return obj.get_absolute_url() + if hasattr(obj, 'get_parent_url'): + return obj.get_parent_url() + return reverse(self.obj_list_url) def get(self, request, *args, **kwargs): @@ -149,7 +150,7 @@ class ObjectEditView(View): 'obj': obj, 'obj_type': self.model._meta.verbose_name, 'form': form, - 'cancel_url': self.get_cancel_url(obj), + 'cancel_url': self.get_redirect_url(obj), }) def post(self, request, *args, **kwargs): @@ -179,18 +180,13 @@ class ObjectEditView(View): if '_addanother' in request.POST: return redirect(request.path) - elif self.success_url: - return redirect(self.success_url) - elif hasattr(obj, 'get_absolute_url'): - return redirect(obj.get_absolute_url()) - elif hasattr(obj, 'get_parent_url'): - return redirect(obj.get_parent_url()) + return redirect(self.get_redirect_url(obj)) return render(request, self.template_name, { 'obj': obj, 'obj_type': self.model._meta.verbose_name, 'form': form, - 'cancel_url': self.get_cancel_url(obj), + 'cancel_url': self.get_redirect_url(obj), }) From a68e82575f55327097f8419096394fe60eaf3830 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 8 Dec 2016 12:33:36 -0500 Subject: [PATCH 8/8] Release v1.7.3 --- netbox/netbox/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index b479420bd..f4b0ccc2c 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -12,7 +12,7 @@ except ImportError: "the documentation.") -VERSION = '1.7.2-r1' +VERSION = '1.7.3' # Import local configuration for setting in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY']: