diff --git a/docs/release-notes/version-2.11.md b/docs/release-notes/version-2.11.md index 5038cf299..356577d09 100644 --- a/docs/release-notes/version-2.11.md +++ b/docs/release-notes/version-2.11.md @@ -4,6 +4,7 @@ ### Enhancements (from Beta) +* [#6097](https://github.com/netbox-community/netbox/issues/6097) - Redirect old slug-based object views * [#6109](https://github.com/netbox-community/netbox/issues/6109) - Add device counts to locations table ### Bug Fixes (from Beta) diff --git a/netbox/circuits/urls.py b/netbox/circuits/urls.py index e634eeeb4..1cea1965e 100644 --- a/netbox/circuits/urls.py +++ b/netbox/circuits/urls.py @@ -2,6 +2,7 @@ from django.urls import path from dcim.views import CableCreateView, PathTraceView from extras.views import ObjectChangeLogView, ObjectJournalView +from utilities.views import SlugRedirectView from . import views from .models import * @@ -15,6 +16,7 @@ urlpatterns = [ path('providers/edit/', views.ProviderBulkEditView.as_view(), name='provider_bulk_edit'), path('providers/delete/', views.ProviderBulkDeleteView.as_view(), name='provider_bulk_delete'), path('providers//', views.ProviderView.as_view(), name='provider'), + path('providers//', SlugRedirectView.as_view(), kwargs={'model': Provider}), path('providers//edit/', views.ProviderEditView.as_view(), name='provider_edit'), path('providers//delete/', views.ProviderDeleteView.as_view(), name='provider_delete'), path('providers//changelog/', ObjectChangeLogView.as_view(), name='provider_changelog', kwargs={'model': Provider}), diff --git a/netbox/dcim/urls.py b/netbox/dcim/urls.py index b23603c97..3c84aae01 100644 --- a/netbox/dcim/urls.py +++ b/netbox/dcim/urls.py @@ -2,6 +2,7 @@ from django.urls import path from extras.views import ImageAttachmentEditView, ObjectChangeLogView, ObjectJournalView from ipam.views import ServiceEditView +from utilities.views import SlugRedirectView from . import views from .models import * @@ -37,6 +38,7 @@ urlpatterns = [ path('sites/edit/', views.SiteBulkEditView.as_view(), name='site_bulk_edit'), path('sites/delete/', views.SiteBulkDeleteView.as_view(), name='site_bulk_delete'), path('sites//', views.SiteView.as_view(), name='site'), + path('sites//', SlugRedirectView.as_view(), kwargs={'model': Site}), path('sites//edit/', views.SiteEditView.as_view(), name='site_edit'), path('sites//delete/', views.SiteDeleteView.as_view(), name='site_delete'), path('sites//changelog/', ObjectChangeLogView.as_view(), name='site_changelog', kwargs={'model': Site}), diff --git a/netbox/tenancy/urls.py b/netbox/tenancy/urls.py index a3db431da..a1f46c7ec 100644 --- a/netbox/tenancy/urls.py +++ b/netbox/tenancy/urls.py @@ -1,6 +1,7 @@ from django.urls import path from extras.views import ObjectChangeLogView, ObjectJournalView +from utilities.views import SlugRedirectView from . import views from .models import Tenant, TenantGroup @@ -25,6 +26,7 @@ urlpatterns = [ path('tenants/edit/', views.TenantBulkEditView.as_view(), name='tenant_bulk_edit'), path('tenants/delete/', views.TenantBulkDeleteView.as_view(), name='tenant_bulk_delete'), path('tenants//', views.TenantView.as_view(), name='tenant'), + path('tenants//', SlugRedirectView.as_view(), kwargs={'model': Tenant}), path('tenants//edit/', views.TenantEditView.as_view(), name='tenant_edit'), path('tenants//delete/', views.TenantDeleteView.as_view(), name='tenant_delete'), path('tenants//changelog/', ObjectChangeLogView.as_view(), name='tenant_changelog', kwargs={'model': Tenant}), diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index c291a3cf2..a3afcb1c6 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -1,8 +1,10 @@ from django.contrib.auth.mixins import AccessMixin from django.core.exceptions import ImproperlyConfigured +from django.shortcuts import get_object_or_404, redirect from django.urls import reverse from django.urls.exceptions import NoReverseMatch from django.utils.http import is_safe_url +from django.views.generic import View from .permissions import resolve_permission @@ -123,3 +125,14 @@ class GetReturnURLMixin: # If all else fails, return home. Ideally this should never happen. return reverse('home') + + +# +# Views +# + +class SlugRedirectView(View): + + def get(self, request, model, slug): + obj = get_object_or_404(model.objects.restrict(request.user, 'view'), slug=slug) + return redirect(obj.get_absolute_url())