Browse Source

Closes #10608: Register all core model views using register_model_view()

jeremystretch 3 năm trước cách đây
mục cha
commit
b0ba9bd83d

+ 1 - 17
netbox/circuits/urls.py

@@ -1,9 +1,7 @@
 from django.urls import include, path
 from django.urls import include, path
 
 
-from dcim.views import PathTraceView
 from utilities.urls import get_model_urls
 from utilities.urls import get_model_urls
 from . import views
 from . import views
-from .models import CircuitTermination
 
 
 app_name = 'circuits'
 app_name = 'circuits'
 urlpatterns = [
 urlpatterns = [
@@ -14,9 +12,6 @@ urlpatterns = [
     path('providers/import/', views.ProviderBulkImportView.as_view(), name='provider_import'),
     path('providers/import/', views.ProviderBulkImportView.as_view(), name='provider_import'),
     path('providers/edit/', views.ProviderBulkEditView.as_view(), name='provider_bulk_edit'),
     path('providers/edit/', views.ProviderBulkEditView.as_view(), name='provider_bulk_edit'),
     path('providers/delete/', views.ProviderBulkDeleteView.as_view(), name='provider_bulk_delete'),
     path('providers/delete/', views.ProviderBulkDeleteView.as_view(), name='provider_bulk_delete'),
-    path('providers/<int:pk>/', views.ProviderView.as_view(), name='provider'),
-    path('providers/<int:pk>/edit/', views.ProviderEditView.as_view(), name='provider_edit'),
-    path('providers/<int:pk>/delete/', views.ProviderDeleteView.as_view(), name='provider_delete'),
     path('providers/<int:pk>/', include(get_model_urls('circuits', 'provider'))),
     path('providers/<int:pk>/', include(get_model_urls('circuits', 'provider'))),
 
 
     # Provider networks
     # Provider networks
@@ -25,9 +20,6 @@ urlpatterns = [
     path('provider-networks/import/', views.ProviderNetworkBulkImportView.as_view(), name='providernetwork_import'),
     path('provider-networks/import/', views.ProviderNetworkBulkImportView.as_view(), name='providernetwork_import'),
     path('provider-networks/edit/', views.ProviderNetworkBulkEditView.as_view(), name='providernetwork_bulk_edit'),
     path('provider-networks/edit/', views.ProviderNetworkBulkEditView.as_view(), name='providernetwork_bulk_edit'),
     path('provider-networks/delete/', views.ProviderNetworkBulkDeleteView.as_view(), name='providernetwork_bulk_delete'),
     path('provider-networks/delete/', views.ProviderNetworkBulkDeleteView.as_view(), name='providernetwork_bulk_delete'),
-    path('provider-networks/<int:pk>/', views.ProviderNetworkView.as_view(), name='providernetwork'),
-    path('provider-networks/<int:pk>/edit/', views.ProviderNetworkEditView.as_view(), name='providernetwork_edit'),
-    path('provider-networks/<int:pk>/delete/', views.ProviderNetworkDeleteView.as_view(), name='providernetwork_delete'),
     path('provider-networks/<int:pk>/', include(get_model_urls('circuits', 'providernetwork'))),
     path('provider-networks/<int:pk>/', include(get_model_urls('circuits', 'providernetwork'))),
 
 
     # Circuit types
     # Circuit types
@@ -36,9 +28,6 @@ urlpatterns = [
     path('circuit-types/import/', views.CircuitTypeBulkImportView.as_view(), name='circuittype_import'),
     path('circuit-types/import/', views.CircuitTypeBulkImportView.as_view(), name='circuittype_import'),
     path('circuit-types/edit/', views.CircuitTypeBulkEditView.as_view(), name='circuittype_bulk_edit'),
     path('circuit-types/edit/', views.CircuitTypeBulkEditView.as_view(), name='circuittype_bulk_edit'),
     path('circuit-types/delete/', views.CircuitTypeBulkDeleteView.as_view(), name='circuittype_bulk_delete'),
     path('circuit-types/delete/', views.CircuitTypeBulkDeleteView.as_view(), name='circuittype_bulk_delete'),
-    path('circuit-types/<int:pk>/', views.CircuitTypeView.as_view(), name='circuittype'),
-    path('circuit-types/<int:pk>/edit/', views.CircuitTypeEditView.as_view(), name='circuittype_edit'),
-    path('circuit-types/<int:pk>/delete/', views.CircuitTypeDeleteView.as_view(), name='circuittype_delete'),
     path('circuit-types/<int:pk>/', include(get_model_urls('circuits', 'circuittype'))),
     path('circuit-types/<int:pk>/', include(get_model_urls('circuits', 'circuittype'))),
 
 
     # Circuits
     # Circuits
@@ -47,16 +36,11 @@ urlpatterns = [
     path('circuits/import/', views.CircuitBulkImportView.as_view(), name='circuit_import'),
     path('circuits/import/', views.CircuitBulkImportView.as_view(), name='circuit_import'),
     path('circuits/edit/', views.CircuitBulkEditView.as_view(), name='circuit_bulk_edit'),
     path('circuits/edit/', views.CircuitBulkEditView.as_view(), name='circuit_bulk_edit'),
     path('circuits/delete/', views.CircuitBulkDeleteView.as_view(), name='circuit_bulk_delete'),
     path('circuits/delete/', views.CircuitBulkDeleteView.as_view(), name='circuit_bulk_delete'),
-    path('circuits/<int:pk>/', views.CircuitView.as_view(), name='circuit'),
-    path('circuits/<int:pk>/edit/', views.CircuitEditView.as_view(), name='circuit_edit'),
-    path('circuits/<int:pk>/delete/', views.CircuitDeleteView.as_view(), name='circuit_delete'),
     path('circuits/<int:pk>/terminations/swap/', views.CircuitSwapTerminations.as_view(), name='circuit_terminations_swap'),
     path('circuits/<int:pk>/terminations/swap/', views.CircuitSwapTerminations.as_view(), name='circuit_terminations_swap'),
     path('circuits/<int:pk>/', include(get_model_urls('circuits', 'circuit'))),
     path('circuits/<int:pk>/', include(get_model_urls('circuits', 'circuit'))),
 
 
     # Circuit terminations
     # Circuit terminations
     path('circuit-terminations/add/', views.CircuitTerminationEditView.as_view(), name='circuittermination_add'),
     path('circuit-terminations/add/', views.CircuitTerminationEditView.as_view(), name='circuittermination_add'),
-    path('circuit-terminations/<int:pk>/edit/', views.CircuitTerminationEditView.as_view(), name='circuittermination_edit'),
-    path('circuit-terminations/<int:pk>/delete/', views.CircuitTerminationDeleteView.as_view(), name='circuittermination_delete'),
-    path('circuit-terminations/<int:pk>/trace/', PathTraceView.as_view(), name='circuittermination_trace', kwargs={'model': CircuitTermination}),
+    path('circuit-terminations/<int:pk>/', include(get_model_urls('circuits', 'circuittermination'))),
 
 
 ]
 ]

+ 20 - 0
netbox/circuits/views.py

@@ -3,9 +3,11 @@ from django.db import transaction
 from django.db.models import Q
 from django.db.models import Q
 from django.shortcuts import get_object_or_404, redirect, render
 from django.shortcuts import get_object_or_404, redirect, render
 
 
+from dcim.views import PathTraceView
 from netbox.views import generic
 from netbox.views import generic
 from utilities.forms import ConfirmationForm
 from utilities.forms import ConfirmationForm
 from utilities.utils import count_related
 from utilities.utils import count_related
+from utilities.views import register_model_view
 from . import filtersets, forms, tables
 from . import filtersets, forms, tables
 from .models import *
 from .models import *
 
 
@@ -23,6 +25,7 @@ class ProviderListView(generic.ObjectListView):
     table = tables.ProviderTable
     table = tables.ProviderTable
 
 
 
 
+@register_model_view(Provider)
 class ProviderView(generic.ObjectView):
 class ProviderView(generic.ObjectView):
     queryset = Provider.objects.all()
     queryset = Provider.objects.all()
 
 
@@ -41,11 +44,13 @@ class ProviderView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(Provider, 'edit')
 class ProviderEditView(generic.ObjectEditView):
 class ProviderEditView(generic.ObjectEditView):
     queryset = Provider.objects.all()
     queryset = Provider.objects.all()
     form = forms.ProviderForm
     form = forms.ProviderForm
 
 
 
 
+@register_model_view(Provider, 'delete')
 class ProviderDeleteView(generic.ObjectDeleteView):
 class ProviderDeleteView(generic.ObjectDeleteView):
     queryset = Provider.objects.all()
     queryset = Provider.objects.all()
 
 
@@ -84,6 +89,7 @@ class ProviderNetworkListView(generic.ObjectListView):
     table = tables.ProviderNetworkTable
     table = tables.ProviderNetworkTable
 
 
 
 
+@register_model_view(ProviderNetwork)
 class ProviderNetworkView(generic.ObjectView):
 class ProviderNetworkView(generic.ObjectView):
     queryset = ProviderNetwork.objects.all()
     queryset = ProviderNetwork.objects.all()
 
 
@@ -103,11 +109,13 @@ class ProviderNetworkView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(ProviderNetwork, 'edit')
 class ProviderNetworkEditView(generic.ObjectEditView):
 class ProviderNetworkEditView(generic.ObjectEditView):
     queryset = ProviderNetwork.objects.all()
     queryset = ProviderNetwork.objects.all()
     form = forms.ProviderNetworkForm
     form = forms.ProviderNetworkForm
 
 
 
 
+@register_model_view(ProviderNetwork, 'delete')
 class ProviderNetworkDeleteView(generic.ObjectDeleteView):
 class ProviderNetworkDeleteView(generic.ObjectDeleteView):
     queryset = ProviderNetwork.objects.all()
     queryset = ProviderNetwork.objects.all()
 
 
@@ -144,6 +152,7 @@ class CircuitTypeListView(generic.ObjectListView):
     table = tables.CircuitTypeTable
     table = tables.CircuitTypeTable
 
 
 
 
+@register_model_view(CircuitType)
 class CircuitTypeView(generic.ObjectView):
 class CircuitTypeView(generic.ObjectView):
     queryset = CircuitType.objects.all()
     queryset = CircuitType.objects.all()
 
 
@@ -157,11 +166,13 @@ class CircuitTypeView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(CircuitType, 'edit')
 class CircuitTypeEditView(generic.ObjectEditView):
 class CircuitTypeEditView(generic.ObjectEditView):
     queryset = CircuitType.objects.all()
     queryset = CircuitType.objects.all()
     form = forms.CircuitTypeForm
     form = forms.CircuitTypeForm
 
 
 
 
+@register_model_view(CircuitType, 'delete')
 class CircuitTypeDeleteView(generic.ObjectDeleteView):
 class CircuitTypeDeleteView(generic.ObjectDeleteView):
     queryset = CircuitType.objects.all()
     queryset = CircuitType.objects.all()
 
 
@@ -202,15 +213,18 @@ class CircuitListView(generic.ObjectListView):
     table = tables.CircuitTable
     table = tables.CircuitTable
 
 
 
 
+@register_model_view(Circuit)
 class CircuitView(generic.ObjectView):
 class CircuitView(generic.ObjectView):
     queryset = Circuit.objects.all()
     queryset = Circuit.objects.all()
 
 
 
 
+@register_model_view(Circuit, 'edit')
 class CircuitEditView(generic.ObjectEditView):
 class CircuitEditView(generic.ObjectEditView):
     queryset = Circuit.objects.all()
     queryset = Circuit.objects.all()
     form = forms.CircuitForm
     form = forms.CircuitForm
 
 
 
 
+@register_model_view(Circuit, 'delete')
 class CircuitDeleteView(generic.ObjectDeleteView):
 class CircuitDeleteView(generic.ObjectDeleteView):
     queryset = Circuit.objects.all()
     queryset = Circuit.objects.all()
 
 
@@ -318,11 +332,17 @@ class CircuitSwapTerminations(generic.ObjectEditView):
 # Circuit terminations
 # Circuit terminations
 #
 #
 
 
+@register_model_view(CircuitTermination, 'edit')
 class CircuitTerminationEditView(generic.ObjectEditView):
 class CircuitTerminationEditView(generic.ObjectEditView):
     queryset = CircuitTermination.objects.all()
     queryset = CircuitTermination.objects.all()
     form = forms.CircuitTerminationForm
     form = forms.CircuitTerminationForm
     template_name = 'circuits/circuittermination_edit.html'
     template_name = 'circuits/circuittermination_edit.html'
 
 
 
 
+@register_model_view(CircuitTermination, 'delete')
 class CircuitTerminationDeleteView(generic.ObjectDeleteView):
 class CircuitTerminationDeleteView(generic.ObjectDeleteView):
     queryset = CircuitTermination.objects.all()
     queryset = CircuitTermination.objects.all()
+
+
+# Trace view
+register_model_view(CircuitTermination, 'trace', kwargs={'model': CircuitTermination})(PathTraceView)

+ 10 - 121
netbox/dcim/urls.py

@@ -2,9 +2,6 @@ from django.urls import include, path
 
 
 from utilities.urls import get_model_urls
 from utilities.urls import get_model_urls
 from . import views
 from . import views
-from .models import (
-    ConsolePort, ConsoleServerPort, FrontPort, Interface, PowerFeed, PowerPort, PowerOutlet, RearPort,
-)
 
 
 app_name = 'dcim'
 app_name = 'dcim'
 urlpatterns = [
 urlpatterns = [
@@ -15,9 +12,6 @@ urlpatterns = [
     path('regions/import/', views.RegionBulkImportView.as_view(), name='region_import'),
     path('regions/import/', views.RegionBulkImportView.as_view(), name='region_import'),
     path('regions/edit/', views.RegionBulkEditView.as_view(), name='region_bulk_edit'),
     path('regions/edit/', views.RegionBulkEditView.as_view(), name='region_bulk_edit'),
     path('regions/delete/', views.RegionBulkDeleteView.as_view(), name='region_bulk_delete'),
     path('regions/delete/', views.RegionBulkDeleteView.as_view(), name='region_bulk_delete'),
-    path('regions/<int:pk>/', views.RegionView.as_view(), name='region'),
-    path('regions/<int:pk>/edit/', views.RegionEditView.as_view(), name='region_edit'),
-    path('regions/<int:pk>/delete/', views.RegionDeleteView.as_view(), name='region_delete'),
     path('regions/<int:pk>/', include(get_model_urls('dcim', 'region'))),
     path('regions/<int:pk>/', include(get_model_urls('dcim', 'region'))),
 
 
     # Site groups
     # Site groups
@@ -26,9 +20,6 @@ urlpatterns = [
     path('site-groups/import/', views.SiteGroupBulkImportView.as_view(), name='sitegroup_import'),
     path('site-groups/import/', views.SiteGroupBulkImportView.as_view(), name='sitegroup_import'),
     path('site-groups/edit/', views.SiteGroupBulkEditView.as_view(), name='sitegroup_bulk_edit'),
     path('site-groups/edit/', views.SiteGroupBulkEditView.as_view(), name='sitegroup_bulk_edit'),
     path('site-groups/delete/', views.SiteGroupBulkDeleteView.as_view(), name='sitegroup_bulk_delete'),
     path('site-groups/delete/', views.SiteGroupBulkDeleteView.as_view(), name='sitegroup_bulk_delete'),
-    path('site-groups/<int:pk>/', views.SiteGroupView.as_view(), name='sitegroup'),
-    path('site-groups/<int:pk>/edit/', views.SiteGroupEditView.as_view(), name='sitegroup_edit'),
-    path('site-groups/<int:pk>/delete/', views.SiteGroupDeleteView.as_view(), name='sitegroup_delete'),
     path('site-groups/<int:pk>/', include(get_model_urls('dcim', 'sitegroup'))),
     path('site-groups/<int:pk>/', include(get_model_urls('dcim', 'sitegroup'))),
 
 
     # Sites
     # Sites
@@ -37,9 +28,6 @@ urlpatterns = [
     path('sites/import/', views.SiteBulkImportView.as_view(), name='site_import'),
     path('sites/import/', views.SiteBulkImportView.as_view(), name='site_import'),
     path('sites/edit/', views.SiteBulkEditView.as_view(), name='site_bulk_edit'),
     path('sites/edit/', views.SiteBulkEditView.as_view(), name='site_bulk_edit'),
     path('sites/delete/', views.SiteBulkDeleteView.as_view(), name='site_bulk_delete'),
     path('sites/delete/', views.SiteBulkDeleteView.as_view(), name='site_bulk_delete'),
-    path('sites/<int:pk>/', views.SiteView.as_view(), name='site'),
-    path('sites/<int:pk>/edit/', views.SiteEditView.as_view(), name='site_edit'),
-    path('sites/<int:pk>/delete/', views.SiteDeleteView.as_view(), name='site_delete'),
     path('sites/<int:pk>/', include(get_model_urls('dcim', 'site'))),
     path('sites/<int:pk>/', include(get_model_urls('dcim', 'site'))),
 
 
     # Locations
     # Locations
@@ -48,9 +36,6 @@ urlpatterns = [
     path('locations/import/', views.LocationBulkImportView.as_view(), name='location_import'),
     path('locations/import/', views.LocationBulkImportView.as_view(), name='location_import'),
     path('locations/edit/', views.LocationBulkEditView.as_view(), name='location_bulk_edit'),
     path('locations/edit/', views.LocationBulkEditView.as_view(), name='location_bulk_edit'),
     path('locations/delete/', views.LocationBulkDeleteView.as_view(), name='location_bulk_delete'),
     path('locations/delete/', views.LocationBulkDeleteView.as_view(), name='location_bulk_delete'),
-    path('locations/<int:pk>/', views.LocationView.as_view(), name='location'),
-    path('locations/<int:pk>/edit/', views.LocationEditView.as_view(), name='location_edit'),
-    path('locations/<int:pk>/delete/', views.LocationDeleteView.as_view(), name='location_delete'),
     path('locations/<int:pk>/', include(get_model_urls('dcim', 'location'))),
     path('locations/<int:pk>/', include(get_model_urls('dcim', 'location'))),
 
 
     # Rack roles
     # Rack roles
@@ -59,9 +44,6 @@ urlpatterns = [
     path('rack-roles/import/', views.RackRoleBulkImportView.as_view(), name='rackrole_import'),
     path('rack-roles/import/', views.RackRoleBulkImportView.as_view(), name='rackrole_import'),
     path('rack-roles/edit/', views.RackRoleBulkEditView.as_view(), name='rackrole_bulk_edit'),
     path('rack-roles/edit/', views.RackRoleBulkEditView.as_view(), name='rackrole_bulk_edit'),
     path('rack-roles/delete/', views.RackRoleBulkDeleteView.as_view(), name='rackrole_bulk_delete'),
     path('rack-roles/delete/', views.RackRoleBulkDeleteView.as_view(), name='rackrole_bulk_delete'),
-    path('rack-roles/<int:pk>/', views.RackRoleView.as_view(), name='rackrole'),
-    path('rack-roles/<int:pk>/edit/', views.RackRoleEditView.as_view(), name='rackrole_edit'),
-    path('rack-roles/<int:pk>/delete/', views.RackRoleDeleteView.as_view(), name='rackrole_delete'),
     path('rack-roles/<int:pk>/', include(get_model_urls('dcim', 'rackrole'))),
     path('rack-roles/<int:pk>/', include(get_model_urls('dcim', 'rackrole'))),
 
 
     # Rack reservations
     # Rack reservations
@@ -70,9 +52,6 @@ urlpatterns = [
     path('rack-reservations/import/', views.RackReservationImportView.as_view(), name='rackreservation_import'),
     path('rack-reservations/import/', views.RackReservationImportView.as_view(), name='rackreservation_import'),
     path('rack-reservations/edit/', views.RackReservationBulkEditView.as_view(), name='rackreservation_bulk_edit'),
     path('rack-reservations/edit/', views.RackReservationBulkEditView.as_view(), name='rackreservation_bulk_edit'),
     path('rack-reservations/delete/', views.RackReservationBulkDeleteView.as_view(), name='rackreservation_bulk_delete'),
     path('rack-reservations/delete/', views.RackReservationBulkDeleteView.as_view(), name='rackreservation_bulk_delete'),
-    path('rack-reservations/<int:pk>/', views.RackReservationView.as_view(), name='rackreservation'),
-    path('rack-reservations/<int:pk>/edit/', views.RackReservationEditView.as_view(), name='rackreservation_edit'),
-    path('rack-reservations/<int:pk>/delete/', views.RackReservationDeleteView.as_view(), name='rackreservation_delete'),
     path('rack-reservations/<int:pk>/', include(get_model_urls('dcim', 'rackreservation'))),
     path('rack-reservations/<int:pk>/', include(get_model_urls('dcim', 'rackreservation'))),
 
 
     # Racks
     # Racks
@@ -82,9 +61,6 @@ urlpatterns = [
     path('racks/import/', views.RackBulkImportView.as_view(), name='rack_import'),
     path('racks/import/', views.RackBulkImportView.as_view(), name='rack_import'),
     path('racks/edit/', views.RackBulkEditView.as_view(), name='rack_bulk_edit'),
     path('racks/edit/', views.RackBulkEditView.as_view(), name='rack_bulk_edit'),
     path('racks/delete/', views.RackBulkDeleteView.as_view(), name='rack_bulk_delete'),
     path('racks/delete/', views.RackBulkDeleteView.as_view(), name='rack_bulk_delete'),
-    path('racks/<int:pk>/', views.RackView.as_view(), name='rack'),
-    path('racks/<int:pk>/edit/', views.RackEditView.as_view(), name='rack_edit'),
-    path('racks/<int:pk>/delete/', views.RackDeleteView.as_view(), name='rack_delete'),
     path('racks/<int:pk>/', include(get_model_urls('dcim', 'rack'))),
     path('racks/<int:pk>/', include(get_model_urls('dcim', 'rack'))),
 
 
     # Manufacturers
     # Manufacturers
@@ -93,9 +69,6 @@ urlpatterns = [
     path('manufacturers/import/', views.ManufacturerBulkImportView.as_view(), name='manufacturer_import'),
     path('manufacturers/import/', views.ManufacturerBulkImportView.as_view(), name='manufacturer_import'),
     path('manufacturers/edit/', views.ManufacturerBulkEditView.as_view(), name='manufacturer_bulk_edit'),
     path('manufacturers/edit/', views.ManufacturerBulkEditView.as_view(), name='manufacturer_bulk_edit'),
     path('manufacturers/delete/', views.ManufacturerBulkDeleteView.as_view(), name='manufacturer_bulk_delete'),
     path('manufacturers/delete/', views.ManufacturerBulkDeleteView.as_view(), name='manufacturer_bulk_delete'),
-    path('manufacturers/<int:pk>/', views.ManufacturerView.as_view(), name='manufacturer'),
-    path('manufacturers/<int:pk>/edit/', views.ManufacturerEditView.as_view(), name='manufacturer_edit'),
-    path('manufacturers/<int:pk>/delete/', views.ManufacturerDeleteView.as_view(), name='manufacturer_delete'),
     path('manufacturers/<int:pk>/', include(get_model_urls('dcim', 'manufacturer'))),
     path('manufacturers/<int:pk>/', include(get_model_urls('dcim', 'manufacturer'))),
 
 
     # Device types
     # Device types
@@ -104,9 +77,6 @@ urlpatterns = [
     path('device-types/import/', views.DeviceTypeImportView.as_view(), name='devicetype_import'),
     path('device-types/import/', views.DeviceTypeImportView.as_view(), name='devicetype_import'),
     path('device-types/edit/', views.DeviceTypeBulkEditView.as_view(), name='devicetype_bulk_edit'),
     path('device-types/edit/', views.DeviceTypeBulkEditView.as_view(), name='devicetype_bulk_edit'),
     path('device-types/delete/', views.DeviceTypeBulkDeleteView.as_view(), name='devicetype_bulk_delete'),
     path('device-types/delete/', views.DeviceTypeBulkDeleteView.as_view(), name='devicetype_bulk_delete'),
-    path('device-types/<int:pk>/', views.DeviceTypeView.as_view(), name='devicetype'),
-    path('device-types/<int:pk>/edit/', views.DeviceTypeEditView.as_view(), name='devicetype_edit'),
-    path('device-types/<int:pk>/delete/', views.DeviceTypeDeleteView.as_view(), name='devicetype_delete'),
     path('device-types/<int:pk>/', include(get_model_urls('dcim', 'devicetype'))),
     path('device-types/<int:pk>/', include(get_model_urls('dcim', 'devicetype'))),
 
 
     # Module types
     # Module types
@@ -115,9 +85,6 @@ urlpatterns = [
     path('module-types/import/', views.ModuleTypeImportView.as_view(), name='moduletype_import'),
     path('module-types/import/', views.ModuleTypeImportView.as_view(), name='moduletype_import'),
     path('module-types/edit/', views.ModuleTypeBulkEditView.as_view(), name='moduletype_bulk_edit'),
     path('module-types/edit/', views.ModuleTypeBulkEditView.as_view(), name='moduletype_bulk_edit'),
     path('module-types/delete/', views.ModuleTypeBulkDeleteView.as_view(), name='moduletype_bulk_delete'),
     path('module-types/delete/', views.ModuleTypeBulkDeleteView.as_view(), name='moduletype_bulk_delete'),
-    path('module-types/<int:pk>/', views.ModuleTypeView.as_view(), name='moduletype'),
-    path('module-types/<int:pk>/edit/', views.ModuleTypeEditView.as_view(), name='moduletype_edit'),
-    path('module-types/<int:pk>/delete/', views.ModuleTypeDeleteView.as_view(), name='moduletype_delete'),
     path('module-types/<int:pk>/', include(get_model_urls('dcim', 'moduletype'))),
     path('module-types/<int:pk>/', include(get_model_urls('dcim', 'moduletype'))),
 
 
     # Console port templates
     # Console port templates
@@ -125,80 +92,70 @@ urlpatterns = [
     path('console-port-templates/edit/', views.ConsolePortTemplateBulkEditView.as_view(), name='consoleporttemplate_bulk_edit'),
     path('console-port-templates/edit/', views.ConsolePortTemplateBulkEditView.as_view(), name='consoleporttemplate_bulk_edit'),
     path('console-port-templates/rename/', views.ConsolePortTemplateBulkRenameView.as_view(), name='consoleporttemplate_bulk_rename'),
     path('console-port-templates/rename/', views.ConsolePortTemplateBulkRenameView.as_view(), name='consoleporttemplate_bulk_rename'),
     path('console-port-templates/delete/', views.ConsolePortTemplateBulkDeleteView.as_view(), name='consoleporttemplate_bulk_delete'),
     path('console-port-templates/delete/', views.ConsolePortTemplateBulkDeleteView.as_view(), name='consoleporttemplate_bulk_delete'),
-    path('console-port-templates/<int:pk>/edit/', views.ConsolePortTemplateEditView.as_view(), name='consoleporttemplate_edit'),
-    path('console-port-templates/<int:pk>/delete/', views.ConsolePortTemplateDeleteView.as_view(), name='consoleporttemplate_delete'),
+    path('console-port-templates/<int:pk>/', include(get_model_urls('dcim', 'consoleporttemplate'))),
 
 
     # Console server port templates
     # Console server port templates
     path('console-server-port-templates/add/', views.ConsoleServerPortTemplateCreateView.as_view(), name='consoleserverporttemplate_add'),
     path('console-server-port-templates/add/', views.ConsoleServerPortTemplateCreateView.as_view(), name='consoleserverporttemplate_add'),
     path('console-server-port-templates/edit/', views.ConsoleServerPortTemplateBulkEditView.as_view(), name='consoleserverporttemplate_bulk_edit'),
     path('console-server-port-templates/edit/', views.ConsoleServerPortTemplateBulkEditView.as_view(), name='consoleserverporttemplate_bulk_edit'),
     path('console-server-port-templates/rename/', views.ConsoleServerPortTemplateBulkRenameView.as_view(), name='consoleserverporttemplate_bulk_rename'),
     path('console-server-port-templates/rename/', views.ConsoleServerPortTemplateBulkRenameView.as_view(), name='consoleserverporttemplate_bulk_rename'),
     path('console-server-port-templates/delete/', views.ConsoleServerPortTemplateBulkDeleteView.as_view(), name='consoleserverporttemplate_bulk_delete'),
     path('console-server-port-templates/delete/', views.ConsoleServerPortTemplateBulkDeleteView.as_view(), name='consoleserverporttemplate_bulk_delete'),
-    path('console-server-port-templates/<int:pk>/edit/', views.ConsoleServerPortTemplateEditView.as_view(), name='consoleserverporttemplate_edit'),
-    path('console-server-port-templates/<int:pk>/delete/', views.ConsoleServerPortTemplateDeleteView.as_view(), name='consoleserverporttemplate_delete'),
+    path('console-server-port-templates/<int:pk>/', include(get_model_urls('dcim', 'consoleserverporttemplate'))),
 
 
     # Power port templates
     # Power port templates
     path('power-port-templates/add/', views.PowerPortTemplateCreateView.as_view(), name='powerporttemplate_add'),
     path('power-port-templates/add/', views.PowerPortTemplateCreateView.as_view(), name='powerporttemplate_add'),
     path('power-port-templates/edit/', views.PowerPortTemplateBulkEditView.as_view(), name='powerporttemplate_bulk_edit'),
     path('power-port-templates/edit/', views.PowerPortTemplateBulkEditView.as_view(), name='powerporttemplate_bulk_edit'),
     path('power-port-templates/rename/', views.PowerPortTemplateBulkRenameView.as_view(), name='powerporttemplate_bulk_rename'),
     path('power-port-templates/rename/', views.PowerPortTemplateBulkRenameView.as_view(), name='powerporttemplate_bulk_rename'),
     path('power-port-templates/delete/', views.PowerPortTemplateBulkDeleteView.as_view(), name='powerporttemplate_bulk_delete'),
     path('power-port-templates/delete/', views.PowerPortTemplateBulkDeleteView.as_view(), name='powerporttemplate_bulk_delete'),
-    path('power-port-templates/<int:pk>/edit/', views.PowerPortTemplateEditView.as_view(), name='powerporttemplate_edit'),
-    path('power-port-templates/<int:pk>/delete/', views.PowerPortTemplateDeleteView.as_view(), name='powerporttemplate_delete'),
+    path('power-port-templates/<int:pk>/', include(get_model_urls('dcim', 'powerporttemplate'))),
 
 
     # Power outlet templates
     # Power outlet templates
     path('power-outlet-templates/add/', views.PowerOutletTemplateCreateView.as_view(), name='poweroutlettemplate_add'),
     path('power-outlet-templates/add/', views.PowerOutletTemplateCreateView.as_view(), name='poweroutlettemplate_add'),
     path('power-outlet-templates/edit/', views.PowerOutletTemplateBulkEditView.as_view(), name='poweroutlettemplate_bulk_edit'),
     path('power-outlet-templates/edit/', views.PowerOutletTemplateBulkEditView.as_view(), name='poweroutlettemplate_bulk_edit'),
     path('power-outlet-templates/rename/', views.PowerOutletTemplateBulkRenameView.as_view(), name='poweroutlettemplate_bulk_rename'),
     path('power-outlet-templates/rename/', views.PowerOutletTemplateBulkRenameView.as_view(), name='poweroutlettemplate_bulk_rename'),
     path('power-outlet-templates/delete/', views.PowerOutletTemplateBulkDeleteView.as_view(), name='poweroutlettemplate_bulk_delete'),
     path('power-outlet-templates/delete/', views.PowerOutletTemplateBulkDeleteView.as_view(), name='poweroutlettemplate_bulk_delete'),
-    path('power-outlet-templates/<int:pk>/edit/', views.PowerOutletTemplateEditView.as_view(), name='poweroutlettemplate_edit'),
-    path('power-outlet-templates/<int:pk>/delete/', views.PowerOutletTemplateDeleteView.as_view(), name='poweroutlettemplate_delete'),
+    path('power-outlet-templates/<int:pk>/', include(get_model_urls('dcim', 'poweroutlettemplate'))),
 
 
     # Interface templates
     # Interface templates
     path('interface-templates/add/', views.InterfaceTemplateCreateView.as_view(), name='interfacetemplate_add'),
     path('interface-templates/add/', views.InterfaceTemplateCreateView.as_view(), name='interfacetemplate_add'),
     path('interface-templates/edit/', views.InterfaceTemplateBulkEditView.as_view(), name='interfacetemplate_bulk_edit'),
     path('interface-templates/edit/', views.InterfaceTemplateBulkEditView.as_view(), name='interfacetemplate_bulk_edit'),
     path('interface-templates/rename/', views.InterfaceTemplateBulkRenameView.as_view(), name='interfacetemplate_bulk_rename'),
     path('interface-templates/rename/', views.InterfaceTemplateBulkRenameView.as_view(), name='interfacetemplate_bulk_rename'),
     path('interface-templates/delete/', views.InterfaceTemplateBulkDeleteView.as_view(), name='interfacetemplate_bulk_delete'),
     path('interface-templates/delete/', views.InterfaceTemplateBulkDeleteView.as_view(), name='interfacetemplate_bulk_delete'),
-    path('interface-templates/<int:pk>/edit/', views.InterfaceTemplateEditView.as_view(), name='interfacetemplate_edit'),
-    path('interface-templates/<int:pk>/delete/', views.InterfaceTemplateDeleteView.as_view(), name='interfacetemplate_delete'),
+    path('interface-templates/<int:pk>/', include(get_model_urls('dcim', 'interfacetemplate'))),
 
 
     # Front port templates
     # Front port templates
     path('front-port-templates/add/', views.FrontPortTemplateCreateView.as_view(), name='frontporttemplate_add'),
     path('front-port-templates/add/', views.FrontPortTemplateCreateView.as_view(), name='frontporttemplate_add'),
     path('front-port-templates/edit/', views.FrontPortTemplateBulkEditView.as_view(), name='frontporttemplate_bulk_edit'),
     path('front-port-templates/edit/', views.FrontPortTemplateBulkEditView.as_view(), name='frontporttemplate_bulk_edit'),
     path('front-port-templates/rename/', views.FrontPortTemplateBulkRenameView.as_view(), name='frontporttemplate_bulk_rename'),
     path('front-port-templates/rename/', views.FrontPortTemplateBulkRenameView.as_view(), name='frontporttemplate_bulk_rename'),
     path('front-port-templates/delete/', views.FrontPortTemplateBulkDeleteView.as_view(), name='frontporttemplate_bulk_delete'),
     path('front-port-templates/delete/', views.FrontPortTemplateBulkDeleteView.as_view(), name='frontporttemplate_bulk_delete'),
-    path('front-port-templates/<int:pk>/edit/', views.FrontPortTemplateEditView.as_view(), name='frontporttemplate_edit'),
-    path('front-port-templates/<int:pk>/delete/', views.FrontPortTemplateDeleteView.as_view(), name='frontporttemplate_delete'),
+    path('front-port-templates/<int:pk>/', include(get_model_urls('dcim', 'frontporttemplate'))),
 
 
     # Rear port templates
     # Rear port templates
     path('rear-port-templates/add/', views.RearPortTemplateCreateView.as_view(), name='rearporttemplate_add'),
     path('rear-port-templates/add/', views.RearPortTemplateCreateView.as_view(), name='rearporttemplate_add'),
     path('rear-port-templates/edit/', views.RearPortTemplateBulkEditView.as_view(), name='rearporttemplate_bulk_edit'),
     path('rear-port-templates/edit/', views.RearPortTemplateBulkEditView.as_view(), name='rearporttemplate_bulk_edit'),
     path('rear-port-templates/rename/', views.RearPortTemplateBulkRenameView.as_view(), name='rearporttemplate_bulk_rename'),
     path('rear-port-templates/rename/', views.RearPortTemplateBulkRenameView.as_view(), name='rearporttemplate_bulk_rename'),
     path('rear-port-templates/delete/', views.RearPortTemplateBulkDeleteView.as_view(), name='rearporttemplate_bulk_delete'),
     path('rear-port-templates/delete/', views.RearPortTemplateBulkDeleteView.as_view(), name='rearporttemplate_bulk_delete'),
-    path('rear-port-templates/<int:pk>/edit/', views.RearPortTemplateEditView.as_view(), name='rearporttemplate_edit'),
-    path('rear-port-templates/<int:pk>/delete/', views.RearPortTemplateDeleteView.as_view(), name='rearporttemplate_delete'),
+    path('rear-port-templates/<int:pk>/', include(get_model_urls('dcim', 'rearporttemplate'))),
 
 
     # Device bay templates
     # Device bay templates
     path('device-bay-templates/add/', views.DeviceBayTemplateCreateView.as_view(), name='devicebaytemplate_add'),
     path('device-bay-templates/add/', views.DeviceBayTemplateCreateView.as_view(), name='devicebaytemplate_add'),
     path('device-bay-templates/edit/', views.DeviceBayTemplateBulkEditView.as_view(), name='devicebaytemplate_bulk_edit'),
     path('device-bay-templates/edit/', views.DeviceBayTemplateBulkEditView.as_view(), name='devicebaytemplate_bulk_edit'),
     path('device-bay-templates/rename/', views.DeviceBayTemplateBulkRenameView.as_view(), name='devicebaytemplate_bulk_rename'),
     path('device-bay-templates/rename/', views.DeviceBayTemplateBulkRenameView.as_view(), name='devicebaytemplate_bulk_rename'),
     path('device-bay-templates/delete/', views.DeviceBayTemplateBulkDeleteView.as_view(), name='devicebaytemplate_bulk_delete'),
     path('device-bay-templates/delete/', views.DeviceBayTemplateBulkDeleteView.as_view(), name='devicebaytemplate_bulk_delete'),
-    path('device-bay-templates/<int:pk>/edit/', views.DeviceBayTemplateEditView.as_view(), name='devicebaytemplate_edit'),
-    path('device-bay-templates/<int:pk>/delete/', views.DeviceBayTemplateDeleteView.as_view(), name='devicebaytemplate_delete'),
+    path('device-bay-templates/<int:pk>/', include(get_model_urls('dcim', 'devicebaytemplate'))),
 
 
     # Module bay templates
     # Module bay templates
     path('module-bay-templates/add/', views.ModuleBayTemplateCreateView.as_view(), name='modulebaytemplate_add'),
     path('module-bay-templates/add/', views.ModuleBayTemplateCreateView.as_view(), name='modulebaytemplate_add'),
     path('module-bay-templates/edit/', views.ModuleBayTemplateBulkEditView.as_view(), name='modulebaytemplate_bulk_edit'),
     path('module-bay-templates/edit/', views.ModuleBayTemplateBulkEditView.as_view(), name='modulebaytemplate_bulk_edit'),
     path('module-bay-templates/rename/', views.ModuleBayTemplateBulkRenameView.as_view(), name='modulebaytemplate_bulk_rename'),
     path('module-bay-templates/rename/', views.ModuleBayTemplateBulkRenameView.as_view(), name='modulebaytemplate_bulk_rename'),
     path('module-bay-templates/delete/', views.ModuleBayTemplateBulkDeleteView.as_view(), name='modulebaytemplate_bulk_delete'),
     path('module-bay-templates/delete/', views.ModuleBayTemplateBulkDeleteView.as_view(), name='modulebaytemplate_bulk_delete'),
-    path('module-bay-templates/<int:pk>/edit/', views.ModuleBayTemplateEditView.as_view(), name='modulebaytemplate_edit'),
-    path('module-bay-templates/<int:pk>/delete/', views.ModuleBayTemplateDeleteView.as_view(), name='modulebaytemplate_delete'),
+    path('module-bay-templates/<int:pk>/', include(get_model_urls('dcim', 'modulebaytemplate'))),
 
 
     # Inventory item templates
     # Inventory item templates
     path('inventory-item-templates/add/', views.InventoryItemTemplateCreateView.as_view(), name='inventoryitemtemplate_add'),
     path('inventory-item-templates/add/', views.InventoryItemTemplateCreateView.as_view(), name='inventoryitemtemplate_add'),
     path('inventory-item-templates/edit/', views.InventoryItemTemplateBulkEditView.as_view(), name='inventoryitemtemplate_bulk_edit'),
     path('inventory-item-templates/edit/', views.InventoryItemTemplateBulkEditView.as_view(), name='inventoryitemtemplate_bulk_edit'),
     path('inventory-item-templates/rename/', views.InventoryItemTemplateBulkRenameView.as_view(), name='inventoryitemtemplate_bulk_rename'),
     path('inventory-item-templates/rename/', views.InventoryItemTemplateBulkRenameView.as_view(), name='inventoryitemtemplate_bulk_rename'),
     path('inventory-item-templates/delete/', views.InventoryItemTemplateBulkDeleteView.as_view(), name='inventoryitemtemplate_bulk_delete'),
     path('inventory-item-templates/delete/', views.InventoryItemTemplateBulkDeleteView.as_view(), name='inventoryitemtemplate_bulk_delete'),
-    path('inventory-item-templates/<int:pk>/edit/', views.InventoryItemTemplateEditView.as_view(), name='inventoryitemtemplate_edit'),
-    path('inventory-item-templates/<int:pk>/delete/', views.InventoryItemTemplateDeleteView.as_view(), name='inventoryitemtemplate_delete'),
+    path('inventory-item-templates/<int:pk>/', include(get_model_urls('dcim', 'inventoryitemtemplate'))),
 
 
     # Device roles
     # Device roles
     path('device-roles/', views.DeviceRoleListView.as_view(), name='devicerole_list'),
     path('device-roles/', views.DeviceRoleListView.as_view(), name='devicerole_list'),
@@ -206,9 +163,6 @@ urlpatterns = [
     path('device-roles/import/', views.DeviceRoleBulkImportView.as_view(), name='devicerole_import'),
     path('device-roles/import/', views.DeviceRoleBulkImportView.as_view(), name='devicerole_import'),
     path('device-roles/edit/', views.DeviceRoleBulkEditView.as_view(), name='devicerole_bulk_edit'),
     path('device-roles/edit/', views.DeviceRoleBulkEditView.as_view(), name='devicerole_bulk_edit'),
     path('device-roles/delete/', views.DeviceRoleBulkDeleteView.as_view(), name='devicerole_bulk_delete'),
     path('device-roles/delete/', views.DeviceRoleBulkDeleteView.as_view(), name='devicerole_bulk_delete'),
-    path('device-roles/<int:pk>/', views.DeviceRoleView.as_view(), name='devicerole'),
-    path('device-roles/<int:pk>/edit/', views.DeviceRoleEditView.as_view(), name='devicerole_edit'),
-    path('device-roles/<int:pk>/delete/', views.DeviceRoleDeleteView.as_view(), name='devicerole_delete'),
     path('device-roles/<int:pk>/', include(get_model_urls('dcim', 'devicerole'))),
     path('device-roles/<int:pk>/', include(get_model_urls('dcim', 'devicerole'))),
 
 
     # Platforms
     # Platforms
@@ -217,9 +171,6 @@ urlpatterns = [
     path('platforms/import/', views.PlatformBulkImportView.as_view(), name='platform_import'),
     path('platforms/import/', views.PlatformBulkImportView.as_view(), name='platform_import'),
     path('platforms/edit/', views.PlatformBulkEditView.as_view(), name='platform_bulk_edit'),
     path('platforms/edit/', views.PlatformBulkEditView.as_view(), name='platform_bulk_edit'),
     path('platforms/delete/', views.PlatformBulkDeleteView.as_view(), name='platform_bulk_delete'),
     path('platforms/delete/', views.PlatformBulkDeleteView.as_view(), name='platform_bulk_delete'),
-    path('platforms/<int:pk>/', views.PlatformView.as_view(), name='platform'),
-    path('platforms/<int:pk>/edit/', views.PlatformEditView.as_view(), name='platform_edit'),
-    path('platforms/<int:pk>/delete/', views.PlatformDeleteView.as_view(), name='platform_delete'),
     path('platforms/<int:pk>/', include(get_model_urls('dcim', 'platform'))),
     path('platforms/<int:pk>/', include(get_model_urls('dcim', 'platform'))),
 
 
     # Devices
     # Devices
@@ -230,9 +181,6 @@ urlpatterns = [
     path('devices/edit/', views.DeviceBulkEditView.as_view(), name='device_bulk_edit'),
     path('devices/edit/', views.DeviceBulkEditView.as_view(), name='device_bulk_edit'),
     path('devices/rename/', views.DeviceBulkRenameView.as_view(), name='device_bulk_rename'),
     path('devices/rename/', views.DeviceBulkRenameView.as_view(), name='device_bulk_rename'),
     path('devices/delete/', views.DeviceBulkDeleteView.as_view(), name='device_bulk_delete'),
     path('devices/delete/', views.DeviceBulkDeleteView.as_view(), name='device_bulk_delete'),
-    path('devices/<int:pk>/', views.DeviceView.as_view(), name='device'),
-    path('devices/<int:pk>/edit/', views.DeviceEditView.as_view(), name='device_edit'),
-    path('devices/<int:pk>/delete/', views.DeviceDeleteView.as_view(), name='device_delete'),
     path('devices/<int:pk>/', include(get_model_urls('dcim', 'device'))),
     path('devices/<int:pk>/', include(get_model_urls('dcim', 'device'))),
 
 
     # Modules
     # Modules
@@ -241,9 +189,6 @@ urlpatterns = [
     path('modules/import/', views.ModuleBulkImportView.as_view(), name='module_import'),
     path('modules/import/', views.ModuleBulkImportView.as_view(), name='module_import'),
     path('modules/edit/', views.ModuleBulkEditView.as_view(), name='module_bulk_edit'),
     path('modules/edit/', views.ModuleBulkEditView.as_view(), name='module_bulk_edit'),
     path('modules/delete/', views.ModuleBulkDeleteView.as_view(), name='module_bulk_delete'),
     path('modules/delete/', views.ModuleBulkDeleteView.as_view(), name='module_bulk_delete'),
-    path('modules/<int:pk>/', views.ModuleView.as_view(), name='module'),
-    path('modules/<int:pk>/edit/', views.ModuleEditView.as_view(), name='module_edit'),
-    path('modules/<int:pk>/delete/', views.ModuleDeleteView.as_view(), name='module_delete'),
     path('modules/<int:pk>/', include(get_model_urls('dcim', 'module'))),
     path('modules/<int:pk>/', include(get_model_urls('dcim', 'module'))),
 
 
     # Console ports
     # Console ports
@@ -254,10 +199,6 @@ urlpatterns = [
     path('console-ports/rename/', views.ConsolePortBulkRenameView.as_view(), name='consoleport_bulk_rename'),
     path('console-ports/rename/', views.ConsolePortBulkRenameView.as_view(), name='consoleport_bulk_rename'),
     path('console-ports/disconnect/', views.ConsolePortBulkDisconnectView.as_view(), name='consoleport_bulk_disconnect'),
     path('console-ports/disconnect/', views.ConsolePortBulkDisconnectView.as_view(), name='consoleport_bulk_disconnect'),
     path('console-ports/delete/', views.ConsolePortBulkDeleteView.as_view(), name='consoleport_bulk_delete'),
     path('console-ports/delete/', views.ConsolePortBulkDeleteView.as_view(), name='consoleport_bulk_delete'),
-    path('console-ports/<int:pk>/', views.ConsolePortView.as_view(), name='consoleport'),
-    path('console-ports/<int:pk>/edit/', views.ConsolePortEditView.as_view(), name='consoleport_edit'),
-    path('console-ports/<int:pk>/delete/', views.ConsolePortDeleteView.as_view(), name='consoleport_delete'),
-    path('console-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='consoleport_trace', kwargs={'model': ConsolePort}),
     path('console-ports/<int:pk>/', include(get_model_urls('dcim', 'consoleport'))),
     path('console-ports/<int:pk>/', include(get_model_urls('dcim', 'consoleport'))),
     path('devices/console-ports/add/', views.DeviceBulkAddConsolePortView.as_view(), name='device_bulk_add_consoleport'),
     path('devices/console-ports/add/', views.DeviceBulkAddConsolePortView.as_view(), name='device_bulk_add_consoleport'),
 
 
@@ -269,10 +210,6 @@ urlpatterns = [
     path('console-server-ports/rename/', views.ConsoleServerPortBulkRenameView.as_view(), name='consoleserverport_bulk_rename'),
     path('console-server-ports/rename/', views.ConsoleServerPortBulkRenameView.as_view(), name='consoleserverport_bulk_rename'),
     path('console-server-ports/disconnect/', views.ConsoleServerPortBulkDisconnectView.as_view(), name='consoleserverport_bulk_disconnect'),
     path('console-server-ports/disconnect/', views.ConsoleServerPortBulkDisconnectView.as_view(), name='consoleserverport_bulk_disconnect'),
     path('console-server-ports/delete/', views.ConsoleServerPortBulkDeleteView.as_view(), name='consoleserverport_bulk_delete'),
     path('console-server-ports/delete/', views.ConsoleServerPortBulkDeleteView.as_view(), name='consoleserverport_bulk_delete'),
-    path('console-server-ports/<int:pk>/', views.ConsoleServerPortView.as_view(), name='consoleserverport'),
-    path('console-server-ports/<int:pk>/edit/', views.ConsoleServerPortEditView.as_view(), name='consoleserverport_edit'),
-    path('console-server-ports/<int:pk>/delete/', views.ConsoleServerPortDeleteView.as_view(), name='consoleserverport_delete'),
-    path('console-server-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='consoleserverport_trace', kwargs={'model': ConsoleServerPort}),
     path('console-server-ports/<int:pk>/', include(get_model_urls('dcim', 'consoleserverport'))),
     path('console-server-ports/<int:pk>/', include(get_model_urls('dcim', 'consoleserverport'))),
     path('devices/console-server-ports/add/', views.DeviceBulkAddConsoleServerPortView.as_view(), name='device_bulk_add_consoleserverport'),
     path('devices/console-server-ports/add/', views.DeviceBulkAddConsoleServerPortView.as_view(), name='device_bulk_add_consoleserverport'),
 
 
@@ -284,10 +221,6 @@ urlpatterns = [
     path('power-ports/rename/', views.PowerPortBulkRenameView.as_view(), name='powerport_bulk_rename'),
     path('power-ports/rename/', views.PowerPortBulkRenameView.as_view(), name='powerport_bulk_rename'),
     path('power-ports/disconnect/', views.PowerPortBulkDisconnectView.as_view(), name='powerport_bulk_disconnect'),
     path('power-ports/disconnect/', views.PowerPortBulkDisconnectView.as_view(), name='powerport_bulk_disconnect'),
     path('power-ports/delete/', views.PowerPortBulkDeleteView.as_view(), name='powerport_bulk_delete'),
     path('power-ports/delete/', views.PowerPortBulkDeleteView.as_view(), name='powerport_bulk_delete'),
-    path('power-ports/<int:pk>/', views.PowerPortView.as_view(), name='powerport'),
-    path('power-ports/<int:pk>/edit/', views.PowerPortEditView.as_view(), name='powerport_edit'),
-    path('power-ports/<int:pk>/delete/', views.PowerPortDeleteView.as_view(), name='powerport_delete'),
-    path('power-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='powerport_trace', kwargs={'model': PowerPort}),
     path('power-ports/<int:pk>/', include(get_model_urls('dcim', 'powerport'))),
     path('power-ports/<int:pk>/', include(get_model_urls('dcim', 'powerport'))),
     path('devices/power-ports/add/', views.DeviceBulkAddPowerPortView.as_view(), name='device_bulk_add_powerport'),
     path('devices/power-ports/add/', views.DeviceBulkAddPowerPortView.as_view(), name='device_bulk_add_powerport'),
 
 
@@ -299,10 +232,6 @@ urlpatterns = [
     path('power-outlets/rename/', views.PowerOutletBulkRenameView.as_view(), name='poweroutlet_bulk_rename'),
     path('power-outlets/rename/', views.PowerOutletBulkRenameView.as_view(), name='poweroutlet_bulk_rename'),
     path('power-outlets/disconnect/', views.PowerOutletBulkDisconnectView.as_view(), name='poweroutlet_bulk_disconnect'),
     path('power-outlets/disconnect/', views.PowerOutletBulkDisconnectView.as_view(), name='poweroutlet_bulk_disconnect'),
     path('power-outlets/delete/', views.PowerOutletBulkDeleteView.as_view(), name='poweroutlet_bulk_delete'),
     path('power-outlets/delete/', views.PowerOutletBulkDeleteView.as_view(), name='poweroutlet_bulk_delete'),
-    path('power-outlets/<int:pk>/', views.PowerOutletView.as_view(), name='poweroutlet'),
-    path('power-outlets/<int:pk>/edit/', views.PowerOutletEditView.as_view(), name='poweroutlet_edit'),
-    path('power-outlets/<int:pk>/delete/', views.PowerOutletDeleteView.as_view(), name='poweroutlet_delete'),
-    path('power-outlets/<int:pk>/trace/', views.PathTraceView.as_view(), name='poweroutlet_trace', kwargs={'model': PowerOutlet}),
     path('power-outlets/<int:pk>/', include(get_model_urls('dcim', 'poweroutlet'))),
     path('power-outlets/<int:pk>/', include(get_model_urls('dcim', 'poweroutlet'))),
     path('devices/power-outlets/add/', views.DeviceBulkAddPowerOutletView.as_view(), name='device_bulk_add_poweroutlet'),
     path('devices/power-outlets/add/', views.DeviceBulkAddPowerOutletView.as_view(), name='device_bulk_add_poweroutlet'),
 
 
@@ -314,10 +243,6 @@ urlpatterns = [
     path('interfaces/rename/', views.InterfaceBulkRenameView.as_view(), name='interface_bulk_rename'),
     path('interfaces/rename/', views.InterfaceBulkRenameView.as_view(), name='interface_bulk_rename'),
     path('interfaces/disconnect/', views.InterfaceBulkDisconnectView.as_view(), name='interface_bulk_disconnect'),
     path('interfaces/disconnect/', views.InterfaceBulkDisconnectView.as_view(), name='interface_bulk_disconnect'),
     path('interfaces/delete/', views.InterfaceBulkDeleteView.as_view(), name='interface_bulk_delete'),
     path('interfaces/delete/', views.InterfaceBulkDeleteView.as_view(), name='interface_bulk_delete'),
-    path('interfaces/<int:pk>/', views.InterfaceView.as_view(), name='interface'),
-    path('interfaces/<int:pk>/edit/', views.InterfaceEditView.as_view(), name='interface_edit'),
-    path('interfaces/<int:pk>/delete/', views.InterfaceDeleteView.as_view(), name='interface_delete'),
-    path('interfaces/<int:pk>/trace/', views.PathTraceView.as_view(), name='interface_trace', kwargs={'model': Interface}),
     path('interfaces/<int:pk>/', include(get_model_urls('dcim', 'interface'))),
     path('interfaces/<int:pk>/', include(get_model_urls('dcim', 'interface'))),
     path('devices/interfaces/add/', views.DeviceBulkAddInterfaceView.as_view(), name='device_bulk_add_interface'),
     path('devices/interfaces/add/', views.DeviceBulkAddInterfaceView.as_view(), name='device_bulk_add_interface'),
 
 
@@ -329,10 +254,6 @@ urlpatterns = [
     path('front-ports/rename/', views.FrontPortBulkRenameView.as_view(), name='frontport_bulk_rename'),
     path('front-ports/rename/', views.FrontPortBulkRenameView.as_view(), name='frontport_bulk_rename'),
     path('front-ports/disconnect/', views.FrontPortBulkDisconnectView.as_view(), name='frontport_bulk_disconnect'),
     path('front-ports/disconnect/', views.FrontPortBulkDisconnectView.as_view(), name='frontport_bulk_disconnect'),
     path('front-ports/delete/', views.FrontPortBulkDeleteView.as_view(), name='frontport_bulk_delete'),
     path('front-ports/delete/', views.FrontPortBulkDeleteView.as_view(), name='frontport_bulk_delete'),
-    path('front-ports/<int:pk>/', views.FrontPortView.as_view(), name='frontport'),
-    path('front-ports/<int:pk>/edit/', views.FrontPortEditView.as_view(), name='frontport_edit'),
-    path('front-ports/<int:pk>/delete/', views.FrontPortDeleteView.as_view(), name='frontport_delete'),
-    path('front-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='frontport_trace', kwargs={'model': FrontPort}),
     path('front-ports/<int:pk>/', include(get_model_urls('dcim', 'frontport'))),
     path('front-ports/<int:pk>/', include(get_model_urls('dcim', 'frontport'))),
     # path('devices/front-ports/add/', views.DeviceBulkAddFrontPortView.as_view(), name='device_bulk_add_frontport'),
     # path('devices/front-ports/add/', views.DeviceBulkAddFrontPortView.as_view(), name='device_bulk_add_frontport'),
 
 
@@ -344,10 +265,6 @@ urlpatterns = [
     path('rear-ports/rename/', views.RearPortBulkRenameView.as_view(), name='rearport_bulk_rename'),
     path('rear-ports/rename/', views.RearPortBulkRenameView.as_view(), name='rearport_bulk_rename'),
     path('rear-ports/disconnect/', views.RearPortBulkDisconnectView.as_view(), name='rearport_bulk_disconnect'),
     path('rear-ports/disconnect/', views.RearPortBulkDisconnectView.as_view(), name='rearport_bulk_disconnect'),
     path('rear-ports/delete/', views.RearPortBulkDeleteView.as_view(), name='rearport_bulk_delete'),
     path('rear-ports/delete/', views.RearPortBulkDeleteView.as_view(), name='rearport_bulk_delete'),
-    path('rear-ports/<int:pk>/', views.RearPortView.as_view(), name='rearport'),
-    path('rear-ports/<int:pk>/edit/', views.RearPortEditView.as_view(), name='rearport_edit'),
-    path('rear-ports/<int:pk>/delete/', views.RearPortDeleteView.as_view(), name='rearport_delete'),
-    path('rear-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='rearport_trace', kwargs={'model': RearPort}),
     path('rear-ports/<int:pk>/', include(get_model_urls('dcim', 'rearport'))),
     path('rear-ports/<int:pk>/', include(get_model_urls('dcim', 'rearport'))),
     path('devices/rear-ports/add/', views.DeviceBulkAddRearPortView.as_view(), name='device_bulk_add_rearport'),
     path('devices/rear-ports/add/', views.DeviceBulkAddRearPortView.as_view(), name='device_bulk_add_rearport'),
 
 
@@ -358,9 +275,6 @@ urlpatterns = [
     path('module-bays/edit/', views.ModuleBayBulkEditView.as_view(), name='modulebay_bulk_edit'),
     path('module-bays/edit/', views.ModuleBayBulkEditView.as_view(), name='modulebay_bulk_edit'),
     path('module-bays/rename/', views.ModuleBayBulkRenameView.as_view(), name='modulebay_bulk_rename'),
     path('module-bays/rename/', views.ModuleBayBulkRenameView.as_view(), name='modulebay_bulk_rename'),
     path('module-bays/delete/', views.ModuleBayBulkDeleteView.as_view(), name='modulebay_bulk_delete'),
     path('module-bays/delete/', views.ModuleBayBulkDeleteView.as_view(), name='modulebay_bulk_delete'),
-    path('module-bays/<int:pk>/', views.ModuleBayView.as_view(), name='modulebay'),
-    path('module-bays/<int:pk>/edit/', views.ModuleBayEditView.as_view(), name='modulebay_edit'),
-    path('module-bays/<int:pk>/delete/', views.ModuleBayDeleteView.as_view(), name='modulebay_delete'),
     path('module-bays/<int:pk>/', include(get_model_urls('dcim', 'modulebay'))),
     path('module-bays/<int:pk>/', include(get_model_urls('dcim', 'modulebay'))),
     path('devices/module-bays/add/', views.DeviceBulkAddModuleBayView.as_view(), name='device_bulk_add_modulebay'),
     path('devices/module-bays/add/', views.DeviceBulkAddModuleBayView.as_view(), name='device_bulk_add_modulebay'),
 
 
@@ -371,11 +285,6 @@ urlpatterns = [
     path('device-bays/edit/', views.DeviceBayBulkEditView.as_view(), name='devicebay_bulk_edit'),
     path('device-bays/edit/', views.DeviceBayBulkEditView.as_view(), name='devicebay_bulk_edit'),
     path('device-bays/rename/', views.DeviceBayBulkRenameView.as_view(), name='devicebay_bulk_rename'),
     path('device-bays/rename/', views.DeviceBayBulkRenameView.as_view(), name='devicebay_bulk_rename'),
     path('device-bays/delete/', views.DeviceBayBulkDeleteView.as_view(), name='devicebay_bulk_delete'),
     path('device-bays/delete/', views.DeviceBayBulkDeleteView.as_view(), name='devicebay_bulk_delete'),
-    path('device-bays/<int:pk>/', views.DeviceBayView.as_view(), name='devicebay'),
-    path('device-bays/<int:pk>/edit/', views.DeviceBayEditView.as_view(), name='devicebay_edit'),
-    path('device-bays/<int:pk>/delete/', views.DeviceBayDeleteView.as_view(), name='devicebay_delete'),
-    path('device-bays/<int:pk>/populate/', views.DeviceBayPopulateView.as_view(), name='devicebay_populate'),
-    path('device-bays/<int:pk>/depopulate/', views.DeviceBayDepopulateView.as_view(), name='devicebay_depopulate'),
     path('device-bays/<int:pk>/', include(get_model_urls('dcim', 'devicebay'))),
     path('device-bays/<int:pk>/', include(get_model_urls('dcim', 'devicebay'))),
     path('devices/device-bays/add/', views.DeviceBulkAddDeviceBayView.as_view(), name='device_bulk_add_devicebay'),
     path('devices/device-bays/add/', views.DeviceBulkAddDeviceBayView.as_view(), name='device_bulk_add_devicebay'),
 
 
@@ -386,9 +295,6 @@ urlpatterns = [
     path('inventory-items/edit/', views.InventoryItemBulkEditView.as_view(), name='inventoryitem_bulk_edit'),
     path('inventory-items/edit/', views.InventoryItemBulkEditView.as_view(), name='inventoryitem_bulk_edit'),
     path('inventory-items/rename/', views.InventoryItemBulkRenameView.as_view(), name='inventoryitem_bulk_rename'),
     path('inventory-items/rename/', views.InventoryItemBulkRenameView.as_view(), name='inventoryitem_bulk_rename'),
     path('inventory-items/delete/', views.InventoryItemBulkDeleteView.as_view(), name='inventoryitem_bulk_delete'),
     path('inventory-items/delete/', views.InventoryItemBulkDeleteView.as_view(), name='inventoryitem_bulk_delete'),
-    path('inventory-items/<int:pk>/', views.InventoryItemView.as_view(), name='inventoryitem'),
-    path('inventory-items/<int:pk>/edit/', views.InventoryItemEditView.as_view(), name='inventoryitem_edit'),
-    path('inventory-items/<int:pk>/delete/', views.InventoryItemDeleteView.as_view(), name='inventoryitem_delete'),
     path('inventory-items/<int:pk>/', include(get_model_urls('dcim', 'inventoryitem'))),
     path('inventory-items/<int:pk>/', include(get_model_urls('dcim', 'inventoryitem'))),
     path('devices/inventory-items/add/', views.DeviceBulkAddInventoryItemView.as_view(), name='device_bulk_add_inventoryitem'),
     path('devices/inventory-items/add/', views.DeviceBulkAddInventoryItemView.as_view(), name='device_bulk_add_inventoryitem'),
 
 
@@ -398,9 +304,6 @@ urlpatterns = [
     path('inventory-item-roles/import/', views.InventoryItemRoleBulkImportView.as_view(), name='inventoryitemrole_import'),
     path('inventory-item-roles/import/', views.InventoryItemRoleBulkImportView.as_view(), name='inventoryitemrole_import'),
     path('inventory-item-roles/edit/', views.InventoryItemRoleBulkEditView.as_view(), name='inventoryitemrole_bulk_edit'),
     path('inventory-item-roles/edit/', views.InventoryItemRoleBulkEditView.as_view(), name='inventoryitemrole_bulk_edit'),
     path('inventory-item-roles/delete/', views.InventoryItemRoleBulkDeleteView.as_view(), name='inventoryitemrole_bulk_delete'),
     path('inventory-item-roles/delete/', views.InventoryItemRoleBulkDeleteView.as_view(), name='inventoryitemrole_bulk_delete'),
-    path('inventory-item-roles/<int:pk>/', views.InventoryItemRoleView.as_view(), name='inventoryitemrole'),
-    path('inventory-item-roles/<int:pk>/edit/', views.InventoryItemRoleEditView.as_view(), name='inventoryitemrole_edit'),
-    path('inventory-item-roles/<int:pk>/delete/', views.InventoryItemRoleDeleteView.as_view(), name='inventoryitemrole_delete'),
     path('inventory-item-roles/<int:pk>/', include(get_model_urls('dcim', 'inventoryitemrole'))),
     path('inventory-item-roles/<int:pk>/', include(get_model_urls('dcim', 'inventoryitemrole'))),
 
 
     # Cables
     # Cables
@@ -409,9 +312,6 @@ urlpatterns = [
     path('cables/import/', views.CableBulkImportView.as_view(), name='cable_import'),
     path('cables/import/', views.CableBulkImportView.as_view(), name='cable_import'),
     path('cables/edit/', views.CableBulkEditView.as_view(), name='cable_bulk_edit'),
     path('cables/edit/', views.CableBulkEditView.as_view(), name='cable_bulk_edit'),
     path('cables/delete/', views.CableBulkDeleteView.as_view(), name='cable_bulk_delete'),
     path('cables/delete/', views.CableBulkDeleteView.as_view(), name='cable_bulk_delete'),
-    path('cables/<int:pk>/', views.CableView.as_view(), name='cable'),
-    path('cables/<int:pk>/edit/', views.CableEditView.as_view(), name='cable_edit'),
-    path('cables/<int:pk>/delete/', views.CableDeleteView.as_view(), name='cable_delete'),
     path('cables/<int:pk>/', include(get_model_urls('dcim', 'cable'))),
     path('cables/<int:pk>/', include(get_model_urls('dcim', 'cable'))),
 
 
     # Console/power/interface connections (read-only)
     # Console/power/interface connections (read-only)
@@ -425,10 +325,6 @@ urlpatterns = [
     path('virtual-chassis/import/', views.VirtualChassisBulkImportView.as_view(), name='virtualchassis_import'),
     path('virtual-chassis/import/', views.VirtualChassisBulkImportView.as_view(), name='virtualchassis_import'),
     path('virtual-chassis/edit/', views.VirtualChassisBulkEditView.as_view(), name='virtualchassis_bulk_edit'),
     path('virtual-chassis/edit/', views.VirtualChassisBulkEditView.as_view(), name='virtualchassis_bulk_edit'),
     path('virtual-chassis/delete/', views.VirtualChassisBulkDeleteView.as_view(), name='virtualchassis_bulk_delete'),
     path('virtual-chassis/delete/', views.VirtualChassisBulkDeleteView.as_view(), name='virtualchassis_bulk_delete'),
-    path('virtual-chassis/<int:pk>/', views.VirtualChassisView.as_view(), name='virtualchassis'),
-    path('virtual-chassis/<int:pk>/edit/', views.VirtualChassisEditView.as_view(), name='virtualchassis_edit'),
-    path('virtual-chassis/<int:pk>/delete/', views.VirtualChassisDeleteView.as_view(), name='virtualchassis_delete'),
-    path('virtual-chassis/<int:pk>/add-member/', views.VirtualChassisAddMemberView.as_view(), name='virtualchassis_add_member'),
     path('virtual-chassis/<int:pk>/', include(get_model_urls('dcim', 'virtualchassis'))),
     path('virtual-chassis/<int:pk>/', include(get_model_urls('dcim', 'virtualchassis'))),
     path('virtual-chassis-members/<int:pk>/delete/', views.VirtualChassisRemoveMemberView.as_view(), name='virtualchassis_remove_member'),
     path('virtual-chassis-members/<int:pk>/delete/', views.VirtualChassisRemoveMemberView.as_view(), name='virtualchassis_remove_member'),
 
 
@@ -438,9 +334,6 @@ urlpatterns = [
     path('power-panels/import/', views.PowerPanelBulkImportView.as_view(), name='powerpanel_import'),
     path('power-panels/import/', views.PowerPanelBulkImportView.as_view(), name='powerpanel_import'),
     path('power-panels/edit/', views.PowerPanelBulkEditView.as_view(), name='powerpanel_bulk_edit'),
     path('power-panels/edit/', views.PowerPanelBulkEditView.as_view(), name='powerpanel_bulk_edit'),
     path('power-panels/delete/', views.PowerPanelBulkDeleteView.as_view(), name='powerpanel_bulk_delete'),
     path('power-panels/delete/', views.PowerPanelBulkDeleteView.as_view(), name='powerpanel_bulk_delete'),
-    path('power-panels/<int:pk>/', views.PowerPanelView.as_view(), name='powerpanel'),
-    path('power-panels/<int:pk>/edit/', views.PowerPanelEditView.as_view(), name='powerpanel_edit'),
-    path('power-panels/<int:pk>/delete/', views.PowerPanelDeleteView.as_view(), name='powerpanel_delete'),
     path('power-panels/<int:pk>/', include(get_model_urls('dcim', 'powerpanel'))),
     path('power-panels/<int:pk>/', include(get_model_urls('dcim', 'powerpanel'))),
 
 
     # Power feeds
     # Power feeds
@@ -450,10 +343,6 @@ urlpatterns = [
     path('power-feeds/edit/', views.PowerFeedBulkEditView.as_view(), name='powerfeed_bulk_edit'),
     path('power-feeds/edit/', views.PowerFeedBulkEditView.as_view(), name='powerfeed_bulk_edit'),
     path('power-feeds/disconnect/', views.PowerFeedBulkDisconnectView.as_view(), name='powerfeed_bulk_disconnect'),
     path('power-feeds/disconnect/', views.PowerFeedBulkDisconnectView.as_view(), name='powerfeed_bulk_disconnect'),
     path('power-feeds/delete/', views.PowerFeedBulkDeleteView.as_view(), name='powerfeed_bulk_delete'),
     path('power-feeds/delete/', views.PowerFeedBulkDeleteView.as_view(), name='powerfeed_bulk_delete'),
-    path('power-feeds/<int:pk>/', views.PowerFeedView.as_view(), name='powerfeed'),
-    path('power-feeds/<int:pk>/edit/', views.PowerFeedEditView.as_view(), name='powerfeed_edit'),
-    path('power-feeds/<int:pk>/delete/', views.PowerFeedDeleteView.as_view(), name='powerfeed_delete'),
-    path('power-feeds/<int:pk>/trace/', views.PathTraceView.as_view(), name='powerfeed_trace', kwargs={'model': PowerFeed}),
     path('power-feeds/<int:pk>/', include(get_model_urls('dcim', 'powerfeed'))),
     path('power-feeds/<int:pk>/', include(get_model_urls('dcim', 'powerfeed'))),
 
 
 ]
 ]

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 215 - 83
netbox/dcim/views.py


+ 2 - 24
netbox/extras/urls.py

@@ -13,9 +13,6 @@ urlpatterns = [
     path('custom-fields/import/', views.CustomFieldBulkImportView.as_view(), name='customfield_import'),
     path('custom-fields/import/', views.CustomFieldBulkImportView.as_view(), name='customfield_import'),
     path('custom-fields/edit/', views.CustomFieldBulkEditView.as_view(), name='customfield_bulk_edit'),
     path('custom-fields/edit/', views.CustomFieldBulkEditView.as_view(), name='customfield_bulk_edit'),
     path('custom-fields/delete/', views.CustomFieldBulkDeleteView.as_view(), name='customfield_bulk_delete'),
     path('custom-fields/delete/', views.CustomFieldBulkDeleteView.as_view(), name='customfield_bulk_delete'),
-    path('custom-fields/<int:pk>/', views.CustomFieldView.as_view(), name='customfield'),
-    path('custom-fields/<int:pk>/edit/', views.CustomFieldEditView.as_view(), name='customfield_edit'),
-    path('custom-fields/<int:pk>/delete/', views.CustomFieldDeleteView.as_view(), name='customfield_delete'),
     path('custom-fields/<int:pk>/', include(get_model_urls('extras', 'customfield'))),
     path('custom-fields/<int:pk>/', include(get_model_urls('extras', 'customfield'))),
 
 
     # Custom links
     # Custom links
@@ -24,9 +21,6 @@ urlpatterns = [
     path('custom-links/import/', views.CustomLinkBulkImportView.as_view(), name='customlink_import'),
     path('custom-links/import/', views.CustomLinkBulkImportView.as_view(), name='customlink_import'),
     path('custom-links/edit/', views.CustomLinkBulkEditView.as_view(), name='customlink_bulk_edit'),
     path('custom-links/edit/', views.CustomLinkBulkEditView.as_view(), name='customlink_bulk_edit'),
     path('custom-links/delete/', views.CustomLinkBulkDeleteView.as_view(), name='customlink_bulk_delete'),
     path('custom-links/delete/', views.CustomLinkBulkDeleteView.as_view(), name='customlink_bulk_delete'),
-    path('custom-links/<int:pk>/', views.CustomLinkView.as_view(), name='customlink'),
-    path('custom-links/<int:pk>/edit/', views.CustomLinkEditView.as_view(), name='customlink_edit'),
-    path('custom-links/<int:pk>/delete/', views.CustomLinkDeleteView.as_view(), name='customlink_delete'),
     path('custom-links/<int:pk>/', include(get_model_urls('extras', 'customlink'))),
     path('custom-links/<int:pk>/', include(get_model_urls('extras', 'customlink'))),
 
 
     # Export templates
     # Export templates
@@ -35,9 +29,6 @@ urlpatterns = [
     path('export-templates/import/', views.ExportTemplateBulkImportView.as_view(), name='exporttemplate_import'),
     path('export-templates/import/', views.ExportTemplateBulkImportView.as_view(), name='exporttemplate_import'),
     path('export-templates/edit/', views.ExportTemplateBulkEditView.as_view(), name='exporttemplate_bulk_edit'),
     path('export-templates/edit/', views.ExportTemplateBulkEditView.as_view(), name='exporttemplate_bulk_edit'),
     path('export-templates/delete/', views.ExportTemplateBulkDeleteView.as_view(), name='exporttemplate_bulk_delete'),
     path('export-templates/delete/', views.ExportTemplateBulkDeleteView.as_view(), name='exporttemplate_bulk_delete'),
-    path('export-templates/<int:pk>/', views.ExportTemplateView.as_view(), name='exporttemplate'),
-    path('export-templates/<int:pk>/edit/', views.ExportTemplateEditView.as_view(), name='exporttemplate_edit'),
-    path('export-templates/<int:pk>/delete/', views.ExportTemplateDeleteView.as_view(), name='exporttemplate_delete'),
     path('export-templates/<int:pk>/', include(get_model_urls('extras', 'exporttemplate'))),
     path('export-templates/<int:pk>/', include(get_model_urls('extras', 'exporttemplate'))),
 
 
     # Webhooks
     # Webhooks
@@ -46,9 +37,6 @@ urlpatterns = [
     path('webhooks/import/', views.WebhookBulkImportView.as_view(), name='webhook_import'),
     path('webhooks/import/', views.WebhookBulkImportView.as_view(), name='webhook_import'),
     path('webhooks/edit/', views.WebhookBulkEditView.as_view(), name='webhook_bulk_edit'),
     path('webhooks/edit/', views.WebhookBulkEditView.as_view(), name='webhook_bulk_edit'),
     path('webhooks/delete/', views.WebhookBulkDeleteView.as_view(), name='webhook_bulk_delete'),
     path('webhooks/delete/', views.WebhookBulkDeleteView.as_view(), name='webhook_bulk_delete'),
-    path('webhooks/<int:pk>/', views.WebhookView.as_view(), name='webhook'),
-    path('webhooks/<int:pk>/edit/', views.WebhookEditView.as_view(), name='webhook_edit'),
-    path('webhooks/<int:pk>/delete/', views.WebhookDeleteView.as_view(), name='webhook_delete'),
     path('webhooks/<int:pk>/', include(get_model_urls('extras', 'webhook'))),
     path('webhooks/<int:pk>/', include(get_model_urls('extras', 'webhook'))),
 
 
     # Tags
     # Tags
@@ -57,9 +45,6 @@ urlpatterns = [
     path('tags/import/', views.TagBulkImportView.as_view(), name='tag_import'),
     path('tags/import/', views.TagBulkImportView.as_view(), name='tag_import'),
     path('tags/edit/', views.TagBulkEditView.as_view(), name='tag_bulk_edit'),
     path('tags/edit/', views.TagBulkEditView.as_view(), name='tag_bulk_edit'),
     path('tags/delete/', views.TagBulkDeleteView.as_view(), name='tag_bulk_delete'),
     path('tags/delete/', views.TagBulkDeleteView.as_view(), name='tag_bulk_delete'),
-    path('tags/<int:pk>/', views.TagView.as_view(), name='tag'),
-    path('tags/<int:pk>/edit/', views.TagEditView.as_view(), name='tag_edit'),
-    path('tags/<int:pk>/delete/', views.TagDeleteView.as_view(), name='tag_delete'),
     path('tags/<int:pk>/', include(get_model_urls('extras', 'tag'))),
     path('tags/<int:pk>/', include(get_model_urls('extras', 'tag'))),
 
 
     # Config contexts
     # Config contexts
@@ -67,29 +52,22 @@ urlpatterns = [
     path('config-contexts/add/', views.ConfigContextEditView.as_view(), name='configcontext_add'),
     path('config-contexts/add/', views.ConfigContextEditView.as_view(), name='configcontext_add'),
     path('config-contexts/edit/', views.ConfigContextBulkEditView.as_view(), name='configcontext_bulk_edit'),
     path('config-contexts/edit/', views.ConfigContextBulkEditView.as_view(), name='configcontext_bulk_edit'),
     path('config-contexts/delete/', views.ConfigContextBulkDeleteView.as_view(), name='configcontext_bulk_delete'),
     path('config-contexts/delete/', views.ConfigContextBulkDeleteView.as_view(), name='configcontext_bulk_delete'),
-    path('config-contexts/<int:pk>/', views.ConfigContextView.as_view(), name='configcontext'),
-    path('config-contexts/<int:pk>/edit/', views.ConfigContextEditView.as_view(), name='configcontext_edit'),
-    path('config-contexts/<int:pk>/delete/', views.ConfigContextDeleteView.as_view(), name='configcontext_delete'),
     path('config-contexts/<int:pk>/', include(get_model_urls('extras', 'configcontext'))),
     path('config-contexts/<int:pk>/', include(get_model_urls('extras', 'configcontext'))),
 
 
     # Image attachments
     # Image attachments
     path('image-attachments/add/', views.ImageAttachmentEditView.as_view(), name='imageattachment_add'),
     path('image-attachments/add/', views.ImageAttachmentEditView.as_view(), name='imageattachment_add'),
-    path('image-attachments/<int:pk>/edit/', views.ImageAttachmentEditView.as_view(), name='imageattachment_edit'),
-    path('image-attachments/<int:pk>/delete/', views.ImageAttachmentDeleteView.as_view(), name='imageattachment_delete'),
+    path('image-attachments/<int:pk>/', include(get_model_urls('extras', 'imageattachment'))),
 
 
     # Journal entries
     # Journal entries
     path('journal-entries/', views.JournalEntryListView.as_view(), name='journalentry_list'),
     path('journal-entries/', views.JournalEntryListView.as_view(), name='journalentry_list'),
     path('journal-entries/add/', views.JournalEntryEditView.as_view(), name='journalentry_add'),
     path('journal-entries/add/', views.JournalEntryEditView.as_view(), name='journalentry_add'),
     path('journal-entries/edit/', views.JournalEntryBulkEditView.as_view(), name='journalentry_bulk_edit'),
     path('journal-entries/edit/', views.JournalEntryBulkEditView.as_view(), name='journalentry_bulk_edit'),
     path('journal-entries/delete/', views.JournalEntryBulkDeleteView.as_view(), name='journalentry_bulk_delete'),
     path('journal-entries/delete/', views.JournalEntryBulkDeleteView.as_view(), name='journalentry_bulk_delete'),
-    path('journal-entries/<int:pk>/', views.JournalEntryView.as_view(), name='journalentry'),
-    path('journal-entries/<int:pk>/edit/', views.JournalEntryEditView.as_view(), name='journalentry_edit'),
-    path('journal-entries/<int:pk>/delete/', views.JournalEntryDeleteView.as_view(), name='journalentry_delete'),
     path('journal-entries/<int:pk>/', include(get_model_urls('extras', 'journalentry'))),
     path('journal-entries/<int:pk>/', include(get_model_urls('extras', 'journalentry'))),
 
 
     # Change logging
     # Change logging
     path('changelog/', views.ObjectChangeListView.as_view(), name='objectchange_list'),
     path('changelog/', views.ObjectChangeListView.as_view(), name='objectchange_list'),
-    path('changelog/<int:pk>/', views.ObjectChangeView.as_view(), name='objectchange'),
+    path('changelog/<int:pk>/', include(get_model_urls('extras', 'objectchange'))),
 
 
     # Reports
     # Reports
     path('reports/', views.ReportListView.as_view(), name='report_list'),
     path('reports/', views.ReportListView.as_view(), name='report_list'),

+ 25 - 1
netbox/extras/views.py

@@ -12,7 +12,7 @@ from netbox.views import generic
 from utilities.forms import ConfirmationForm
 from utilities.forms import ConfirmationForm
 from utilities.htmx import is_htmx
 from utilities.htmx import is_htmx
 from utilities.utils import copy_safe_request, count_related, get_viewname, normalize_querydict, shallow_compare_dict
 from utilities.utils import copy_safe_request, count_related, get_viewname, normalize_querydict, shallow_compare_dict
-from utilities.views import ContentTypePermissionRequiredMixin
+from utilities.views import ContentTypePermissionRequiredMixin, register_model_view
 from . import filtersets, forms, tables
 from . import filtersets, forms, tables
 from .choices import JobResultStatusChoices
 from .choices import JobResultStatusChoices
 from .models import *
 from .models import *
@@ -31,15 +31,18 @@ class CustomFieldListView(generic.ObjectListView):
     table = tables.CustomFieldTable
     table = tables.CustomFieldTable
 
 
 
 
+@register_model_view(CustomField)
 class CustomFieldView(generic.ObjectView):
 class CustomFieldView(generic.ObjectView):
     queryset = CustomField.objects.all()
     queryset = CustomField.objects.all()
 
 
 
 
+@register_model_view(CustomField, 'edit')
 class CustomFieldEditView(generic.ObjectEditView):
 class CustomFieldEditView(generic.ObjectEditView):
     queryset = CustomField.objects.all()
     queryset = CustomField.objects.all()
     form = forms.CustomFieldForm
     form = forms.CustomFieldForm
 
 
 
 
+@register_model_view(CustomField, 'delete')
 class CustomFieldDeleteView(generic.ObjectDeleteView):
 class CustomFieldDeleteView(generic.ObjectDeleteView):
     queryset = CustomField.objects.all()
     queryset = CustomField.objects.all()
 
 
@@ -74,15 +77,18 @@ class CustomLinkListView(generic.ObjectListView):
     table = tables.CustomLinkTable
     table = tables.CustomLinkTable
 
 
 
 
+@register_model_view(CustomLink)
 class CustomLinkView(generic.ObjectView):
 class CustomLinkView(generic.ObjectView):
     queryset = CustomLink.objects.all()
     queryset = CustomLink.objects.all()
 
 
 
 
+@register_model_view(CustomLink, 'edit')
 class CustomLinkEditView(generic.ObjectEditView):
 class CustomLinkEditView(generic.ObjectEditView):
     queryset = CustomLink.objects.all()
     queryset = CustomLink.objects.all()
     form = forms.CustomLinkForm
     form = forms.CustomLinkForm
 
 
 
 
+@register_model_view(CustomLink, 'delete')
 class CustomLinkDeleteView(generic.ObjectDeleteView):
 class CustomLinkDeleteView(generic.ObjectDeleteView):
     queryset = CustomLink.objects.all()
     queryset = CustomLink.objects.all()
 
 
@@ -117,15 +123,18 @@ class ExportTemplateListView(generic.ObjectListView):
     table = tables.ExportTemplateTable
     table = tables.ExportTemplateTable
 
 
 
 
+@register_model_view(ExportTemplate)
 class ExportTemplateView(generic.ObjectView):
 class ExportTemplateView(generic.ObjectView):
     queryset = ExportTemplate.objects.all()
     queryset = ExportTemplate.objects.all()
 
 
 
 
+@register_model_view(ExportTemplate, 'edit')
 class ExportTemplateEditView(generic.ObjectEditView):
 class ExportTemplateEditView(generic.ObjectEditView):
     queryset = ExportTemplate.objects.all()
     queryset = ExportTemplate.objects.all()
     form = forms.ExportTemplateForm
     form = forms.ExportTemplateForm
 
 
 
 
+@register_model_view(ExportTemplate, 'delete')
 class ExportTemplateDeleteView(generic.ObjectDeleteView):
 class ExportTemplateDeleteView(generic.ObjectDeleteView):
     queryset = ExportTemplate.objects.all()
     queryset = ExportTemplate.objects.all()
 
 
@@ -160,15 +169,18 @@ class WebhookListView(generic.ObjectListView):
     table = tables.WebhookTable
     table = tables.WebhookTable
 
 
 
 
+@register_model_view(Webhook)
 class WebhookView(generic.ObjectView):
 class WebhookView(generic.ObjectView):
     queryset = Webhook.objects.all()
     queryset = Webhook.objects.all()
 
 
 
 
+@register_model_view(Webhook, 'edit')
 class WebhookEditView(generic.ObjectEditView):
 class WebhookEditView(generic.ObjectEditView):
     queryset = Webhook.objects.all()
     queryset = Webhook.objects.all()
     form = forms.WebhookForm
     form = forms.WebhookForm
 
 
 
 
+@register_model_view(Webhook, 'delete')
 class WebhookDeleteView(generic.ObjectDeleteView):
 class WebhookDeleteView(generic.ObjectDeleteView):
     queryset = Webhook.objects.all()
     queryset = Webhook.objects.all()
 
 
@@ -205,6 +217,7 @@ class TagListView(generic.ObjectListView):
     table = tables.TagTable
     table = tables.TagTable
 
 
 
 
+@register_model_view(Tag)
 class TagView(generic.ObjectView):
 class TagView(generic.ObjectView):
     queryset = Tag.objects.all()
     queryset = Tag.objects.all()
 
 
@@ -230,11 +243,13 @@ class TagView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(Tag, 'edit')
 class TagEditView(generic.ObjectEditView):
 class TagEditView(generic.ObjectEditView):
     queryset = Tag.objects.all()
     queryset = Tag.objects.all()
     form = forms.TagForm
     form = forms.TagForm
 
 
 
 
+@register_model_view(Tag, 'delete')
 class TagDeleteView(generic.ObjectDeleteView):
 class TagDeleteView(generic.ObjectDeleteView):
     queryset = Tag.objects.all()
     queryset = Tag.objects.all()
 
 
@@ -272,6 +287,7 @@ class ConfigContextListView(generic.ObjectListView):
     actions = ('add', 'bulk_edit', 'bulk_delete')
     actions = ('add', 'bulk_edit', 'bulk_delete')
 
 
 
 
+@register_model_view(ConfigContext)
 class ConfigContextView(generic.ObjectView):
 class ConfigContextView(generic.ObjectView):
     queryset = ConfigContext.objects.all()
     queryset = ConfigContext.objects.all()
 
 
@@ -309,6 +325,7 @@ class ConfigContextView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(ConfigContext, 'edit')
 class ConfigContextEditView(generic.ObjectEditView):
 class ConfigContextEditView(generic.ObjectEditView):
     queryset = ConfigContext.objects.all()
     queryset = ConfigContext.objects.all()
     form = forms.ConfigContextForm
     form = forms.ConfigContextForm
@@ -321,6 +338,7 @@ class ConfigContextBulkEditView(generic.BulkEditView):
     form = forms.ConfigContextBulkEditForm
     form = forms.ConfigContextBulkEditForm
 
 
 
 
+@register_model_view(ConfigContext, 'delete')
 class ConfigContextDeleteView(generic.ObjectDeleteView):
 class ConfigContextDeleteView(generic.ObjectDeleteView):
     queryset = ConfigContext.objects.all()
     queryset = ConfigContext.objects.all()
 
 
@@ -368,6 +386,7 @@ class ObjectChangeListView(generic.ObjectListView):
     actions = ('export',)
     actions = ('export',)
 
 
 
 
+@register_model_view(ObjectChange)
 class ObjectChangeView(generic.ObjectView):
 class ObjectChangeView(generic.ObjectView):
     queryset = ObjectChange.objects.all()
     queryset = ObjectChange.objects.all()
 
 
@@ -425,6 +444,7 @@ class ObjectChangeView(generic.ObjectView):
 # Image attachments
 # Image attachments
 #
 #
 
 
+@register_model_view(ImageAttachment, 'edit')
 class ImageAttachmentEditView(generic.ObjectEditView):
 class ImageAttachmentEditView(generic.ObjectEditView):
     queryset = ImageAttachment.objects.all()
     queryset = ImageAttachment.objects.all()
     form = forms.ImageAttachmentForm
     form = forms.ImageAttachmentForm
@@ -447,6 +467,7 @@ class ImageAttachmentEditView(generic.ObjectEditView):
         }
         }
 
 
 
 
+@register_model_view(ImageAttachment, 'delete')
 class ImageAttachmentDeleteView(generic.ObjectDeleteView):
 class ImageAttachmentDeleteView(generic.ObjectDeleteView):
     queryset = ImageAttachment.objects.all()
     queryset = ImageAttachment.objects.all()
 
 
@@ -466,10 +487,12 @@ class JournalEntryListView(generic.ObjectListView):
     actions = ('export', 'bulk_edit', 'bulk_delete')
     actions = ('export', 'bulk_edit', 'bulk_delete')
 
 
 
 
+@register_model_view(JournalEntry)
 class JournalEntryView(generic.ObjectView):
 class JournalEntryView(generic.ObjectView):
     queryset = JournalEntry.objects.all()
     queryset = JournalEntry.objects.all()
 
 
 
 
+@register_model_view(JournalEntry, 'edit')
 class JournalEntryEditView(generic.ObjectEditView):
 class JournalEntryEditView(generic.ObjectEditView):
     queryset = JournalEntry.objects.all()
     queryset = JournalEntry.objects.all()
     form = forms.JournalEntryForm
     form = forms.JournalEntryForm
@@ -487,6 +510,7 @@ class JournalEntryEditView(generic.ObjectEditView):
         return reverse(viewname, kwargs={'pk': obj.pk})
         return reverse(viewname, kwargs={'pk': obj.pk})
 
 
 
 
+@register_model_view(JournalEntry, 'delete')
 class JournalEntryDeleteView(generic.ObjectDeleteView):
 class JournalEntryDeleteView(generic.ObjectDeleteView):
     queryset = JournalEntry.objects.all()
     queryset = JournalEntry.objects.all()
 
 

+ 1 - 50
netbox/ipam/urls.py

@@ -12,9 +12,6 @@ urlpatterns = [
     path('asns/import/', views.ASNBulkImportView.as_view(), name='asn_import'),
     path('asns/import/', views.ASNBulkImportView.as_view(), name='asn_import'),
     path('asns/edit/', views.ASNBulkEditView.as_view(), name='asn_bulk_edit'),
     path('asns/edit/', views.ASNBulkEditView.as_view(), name='asn_bulk_edit'),
     path('asns/delete/', views.ASNBulkDeleteView.as_view(), name='asn_bulk_delete'),
     path('asns/delete/', views.ASNBulkDeleteView.as_view(), name='asn_bulk_delete'),
-    path('asns/<int:pk>/', views.ASNView.as_view(), name='asn'),
-    path('asns/<int:pk>/edit/', views.ASNEditView.as_view(), name='asn_edit'),
-    path('asns/<int:pk>/delete/', views.ASNDeleteView.as_view(), name='asn_delete'),
     path('asns/<int:pk>/', include(get_model_urls('ipam', 'asn'))),
     path('asns/<int:pk>/', include(get_model_urls('ipam', 'asn'))),
 
 
     # VRFs
     # VRFs
@@ -23,9 +20,6 @@ urlpatterns = [
     path('vrfs/import/', views.VRFBulkImportView.as_view(), name='vrf_import'),
     path('vrfs/import/', views.VRFBulkImportView.as_view(), name='vrf_import'),
     path('vrfs/edit/', views.VRFBulkEditView.as_view(), name='vrf_bulk_edit'),
     path('vrfs/edit/', views.VRFBulkEditView.as_view(), name='vrf_bulk_edit'),
     path('vrfs/delete/', views.VRFBulkDeleteView.as_view(), name='vrf_bulk_delete'),
     path('vrfs/delete/', views.VRFBulkDeleteView.as_view(), name='vrf_bulk_delete'),
-    path('vrfs/<int:pk>/', views.VRFView.as_view(), name='vrf'),
-    path('vrfs/<int:pk>/edit/', views.VRFEditView.as_view(), name='vrf_edit'),
-    path('vrfs/<int:pk>/delete/', views.VRFDeleteView.as_view(), name='vrf_delete'),
     path('vrfs/<int:pk>/', include(get_model_urls('ipam', 'vrf'))),
     path('vrfs/<int:pk>/', include(get_model_urls('ipam', 'vrf'))),
 
 
     # Route targets
     # Route targets
@@ -34,9 +28,6 @@ urlpatterns = [
     path('route-targets/import/', views.RouteTargetBulkImportView.as_view(), name='routetarget_import'),
     path('route-targets/import/', views.RouteTargetBulkImportView.as_view(), name='routetarget_import'),
     path('route-targets/edit/', views.RouteTargetBulkEditView.as_view(), name='routetarget_bulk_edit'),
     path('route-targets/edit/', views.RouteTargetBulkEditView.as_view(), name='routetarget_bulk_edit'),
     path('route-targets/delete/', views.RouteTargetBulkDeleteView.as_view(), name='routetarget_bulk_delete'),
     path('route-targets/delete/', views.RouteTargetBulkDeleteView.as_view(), name='routetarget_bulk_delete'),
-    path('route-targets/<int:pk>/', views.RouteTargetView.as_view(), name='routetarget'),
-    path('route-targets/<int:pk>/edit/', views.RouteTargetEditView.as_view(), name='routetarget_edit'),
-    path('route-targets/<int:pk>/delete/', views.RouteTargetDeleteView.as_view(), name='routetarget_delete'),
     path('route-targets/<int:pk>/', include(get_model_urls('ipam', 'routetarget'))),
     path('route-targets/<int:pk>/', include(get_model_urls('ipam', 'routetarget'))),
 
 
     # RIRs
     # RIRs
@@ -45,9 +36,6 @@ urlpatterns = [
     path('rirs/import/', views.RIRBulkImportView.as_view(), name='rir_import'),
     path('rirs/import/', views.RIRBulkImportView.as_view(), name='rir_import'),
     path('rirs/edit/', views.RIRBulkEditView.as_view(), name='rir_bulk_edit'),
     path('rirs/edit/', views.RIRBulkEditView.as_view(), name='rir_bulk_edit'),
     path('rirs/delete/', views.RIRBulkDeleteView.as_view(), name='rir_bulk_delete'),
     path('rirs/delete/', views.RIRBulkDeleteView.as_view(), name='rir_bulk_delete'),
-    path('rirs/<int:pk>/', views.RIRView.as_view(), name='rir'),
-    path('rirs/<int:pk>/edit/', views.RIREditView.as_view(), name='rir_edit'),
-    path('rirs/<int:pk>/delete/', views.RIRDeleteView.as_view(), name='rir_delete'),
     path('rirs/<int:pk>/', include(get_model_urls('ipam', 'rir'))),
     path('rirs/<int:pk>/', include(get_model_urls('ipam', 'rir'))),
 
 
     # Aggregates
     # Aggregates
@@ -56,9 +44,6 @@ urlpatterns = [
     path('aggregates/import/', views.AggregateBulkImportView.as_view(), name='aggregate_import'),
     path('aggregates/import/', views.AggregateBulkImportView.as_view(), name='aggregate_import'),
     path('aggregates/edit/', views.AggregateBulkEditView.as_view(), name='aggregate_bulk_edit'),
     path('aggregates/edit/', views.AggregateBulkEditView.as_view(), name='aggregate_bulk_edit'),
     path('aggregates/delete/', views.AggregateBulkDeleteView.as_view(), name='aggregate_bulk_delete'),
     path('aggregates/delete/', views.AggregateBulkDeleteView.as_view(), name='aggregate_bulk_delete'),
-    path('aggregates/<int:pk>/', views.AggregateView.as_view(), name='aggregate'),
-    path('aggregates/<int:pk>/edit/', views.AggregateEditView.as_view(), name='aggregate_edit'),
-    path('aggregates/<int:pk>/delete/', views.AggregateDeleteView.as_view(), name='aggregate_delete'),
     path('aggregates/<int:pk>/', include(get_model_urls('ipam', 'aggregate'))),
     path('aggregates/<int:pk>/', include(get_model_urls('ipam', 'aggregate'))),
 
 
     # Roles
     # Roles
@@ -67,9 +52,6 @@ urlpatterns = [
     path('roles/import/', views.RoleBulkImportView.as_view(), name='role_import'),
     path('roles/import/', views.RoleBulkImportView.as_view(), name='role_import'),
     path('roles/edit/', views.RoleBulkEditView.as_view(), name='role_bulk_edit'),
     path('roles/edit/', views.RoleBulkEditView.as_view(), name='role_bulk_edit'),
     path('roles/delete/', views.RoleBulkDeleteView.as_view(), name='role_bulk_delete'),
     path('roles/delete/', views.RoleBulkDeleteView.as_view(), name='role_bulk_delete'),
-    path('roles/<int:pk>/', views.RoleView.as_view(), name='role'),
-    path('roles/<int:pk>/edit/', views.RoleEditView.as_view(), name='role_edit'),
-    path('roles/<int:pk>/delete/', views.RoleDeleteView.as_view(), name='role_delete'),
     path('roles/<int:pk>/', include(get_model_urls('ipam', 'role'))),
     path('roles/<int:pk>/', include(get_model_urls('ipam', 'role'))),
 
 
     # Prefixes
     # Prefixes
@@ -78,9 +60,6 @@ urlpatterns = [
     path('prefixes/import/', views.PrefixBulkImportView.as_view(), name='prefix_import'),
     path('prefixes/import/', views.PrefixBulkImportView.as_view(), name='prefix_import'),
     path('prefixes/edit/', views.PrefixBulkEditView.as_view(), name='prefix_bulk_edit'),
     path('prefixes/edit/', views.PrefixBulkEditView.as_view(), name='prefix_bulk_edit'),
     path('prefixes/delete/', views.PrefixBulkDeleteView.as_view(), name='prefix_bulk_delete'),
     path('prefixes/delete/', views.PrefixBulkDeleteView.as_view(), name='prefix_bulk_delete'),
-    path('prefixes/<int:pk>/', views.PrefixView.as_view(), name='prefix'),
-    path('prefixes/<int:pk>/edit/', views.PrefixEditView.as_view(), name='prefix_edit'),
-    path('prefixes/<int:pk>/delete/', views.PrefixDeleteView.as_view(), name='prefix_delete'),
     path('prefixes/<int:pk>/', include(get_model_urls('ipam', 'prefix'))),
     path('prefixes/<int:pk>/', include(get_model_urls('ipam', 'prefix'))),
 
 
     # IP ranges
     # IP ranges
@@ -89,9 +68,6 @@ urlpatterns = [
     path('ip-ranges/import/', views.IPRangeBulkImportView.as_view(), name='iprange_import'),
     path('ip-ranges/import/', views.IPRangeBulkImportView.as_view(), name='iprange_import'),
     path('ip-ranges/edit/', views.IPRangeBulkEditView.as_view(), name='iprange_bulk_edit'),
     path('ip-ranges/edit/', views.IPRangeBulkEditView.as_view(), name='iprange_bulk_edit'),
     path('ip-ranges/delete/', views.IPRangeBulkDeleteView.as_view(), name='iprange_bulk_delete'),
     path('ip-ranges/delete/', views.IPRangeBulkDeleteView.as_view(), name='iprange_bulk_delete'),
-    path('ip-ranges/<int:pk>/', views.IPRangeView.as_view(), name='iprange'),
-    path('ip-ranges/<int:pk>/edit/', views.IPRangeEditView.as_view(), name='iprange_edit'),
-    path('ip-ranges/<int:pk>/delete/', views.IPRangeDeleteView.as_view(), name='iprange_delete'),
     path('ip-ranges/<int:pk>/', include(get_model_urls('ipam', 'iprange'))),
     path('ip-ranges/<int:pk>/', include(get_model_urls('ipam', 'iprange'))),
 
 
     # IP addresses
     # IP addresses
@@ -102,9 +78,6 @@ urlpatterns = [
     path('ip-addresses/edit/', views.IPAddressBulkEditView.as_view(), name='ipaddress_bulk_edit'),
     path('ip-addresses/edit/', views.IPAddressBulkEditView.as_view(), name='ipaddress_bulk_edit'),
     path('ip-addresses/delete/', views.IPAddressBulkDeleteView.as_view(), name='ipaddress_bulk_delete'),
     path('ip-addresses/delete/', views.IPAddressBulkDeleteView.as_view(), name='ipaddress_bulk_delete'),
     path('ip-addresses/assign/', views.IPAddressAssignView.as_view(), name='ipaddress_assign'),
     path('ip-addresses/assign/', views.IPAddressAssignView.as_view(), name='ipaddress_assign'),
-    path('ip-addresses/<int:pk>/', views.IPAddressView.as_view(), name='ipaddress'),
-    path('ip-addresses/<int:pk>/edit/', views.IPAddressEditView.as_view(), name='ipaddress_edit'),
-    path('ip-addresses/<int:pk>/delete/', views.IPAddressDeleteView.as_view(), name='ipaddress_delete'),
     path('ip-addresses/<int:pk>/', include(get_model_urls('ipam', 'ipaddress'))),
     path('ip-addresses/<int:pk>/', include(get_model_urls('ipam', 'ipaddress'))),
 
 
     # FHRP groups
     # FHRP groups
@@ -113,15 +86,11 @@ urlpatterns = [
     path('fhrp-groups/import/', views.FHRPGroupBulkImportView.as_view(), name='fhrpgroup_import'),
     path('fhrp-groups/import/', views.FHRPGroupBulkImportView.as_view(), name='fhrpgroup_import'),
     path('fhrp-groups/edit/', views.FHRPGroupBulkEditView.as_view(), name='fhrpgroup_bulk_edit'),
     path('fhrp-groups/edit/', views.FHRPGroupBulkEditView.as_view(), name='fhrpgroup_bulk_edit'),
     path('fhrp-groups/delete/', views.FHRPGroupBulkDeleteView.as_view(), name='fhrpgroup_bulk_delete'),
     path('fhrp-groups/delete/', views.FHRPGroupBulkDeleteView.as_view(), name='fhrpgroup_bulk_delete'),
-    path('fhrp-groups/<int:pk>/', views.FHRPGroupView.as_view(), name='fhrpgroup'),
-    path('fhrp-groups/<int:pk>/edit/', views.FHRPGroupEditView.as_view(), name='fhrpgroup_edit'),
-    path('fhrp-groups/<int:pk>/delete/', views.FHRPGroupDeleteView.as_view(), name='fhrpgroup_delete'),
     path('fhrp-groups/<int:pk>/', include(get_model_urls('ipam', 'fhrpgroup'))),
     path('fhrp-groups/<int:pk>/', include(get_model_urls('ipam', 'fhrpgroup'))),
 
 
     # FHRP group assignments
     # FHRP group assignments
     path('fhrp-group-assignments/add/', views.FHRPGroupAssignmentEditView.as_view(), name='fhrpgroupassignment_add'),
     path('fhrp-group-assignments/add/', views.FHRPGroupAssignmentEditView.as_view(), name='fhrpgroupassignment_add'),
-    path('fhrp-group-assignments/<int:pk>/edit/', views.FHRPGroupAssignmentEditView.as_view(), name='fhrpgroupassignment_edit'),
-    path('fhrp-group-assignments/<int:pk>/delete/', views.FHRPGroupAssignmentDeleteView.as_view(), name='fhrpgroupassignment_delete'),
+    path('fhrp-group-assignments/<int:pk>/', include(get_model_urls('ipam', 'fhrpgroupassignment'))),
 
 
     # VLAN groups
     # VLAN groups
     path('vlan-groups/', views.VLANGroupListView.as_view(), name='vlangroup_list'),
     path('vlan-groups/', views.VLANGroupListView.as_view(), name='vlangroup_list'),
@@ -129,9 +98,6 @@ urlpatterns = [
     path('vlan-groups/import/', views.VLANGroupBulkImportView.as_view(), name='vlangroup_import'),
     path('vlan-groups/import/', views.VLANGroupBulkImportView.as_view(), name='vlangroup_import'),
     path('vlan-groups/edit/', views.VLANGroupBulkEditView.as_view(), name='vlangroup_bulk_edit'),
     path('vlan-groups/edit/', views.VLANGroupBulkEditView.as_view(), name='vlangroup_bulk_edit'),
     path('vlan-groups/delete/', views.VLANGroupBulkDeleteView.as_view(), name='vlangroup_bulk_delete'),
     path('vlan-groups/delete/', views.VLANGroupBulkDeleteView.as_view(), name='vlangroup_bulk_delete'),
-    path('vlan-groups/<int:pk>/', views.VLANGroupView.as_view(), name='vlangroup'),
-    path('vlan-groups/<int:pk>/edit/', views.VLANGroupEditView.as_view(), name='vlangroup_edit'),
-    path('vlan-groups/<int:pk>/delete/', views.VLANGroupDeleteView.as_view(), name='vlangroup_delete'),
     path('vlan-groups/<int:pk>/', include(get_model_urls('ipam', 'vlangroup'))),
     path('vlan-groups/<int:pk>/', include(get_model_urls('ipam', 'vlangroup'))),
 
 
     # VLANs
     # VLANs
@@ -140,9 +106,6 @@ urlpatterns = [
     path('vlans/import/', views.VLANBulkImportView.as_view(), name='vlan_import'),
     path('vlans/import/', views.VLANBulkImportView.as_view(), name='vlan_import'),
     path('vlans/edit/', views.VLANBulkEditView.as_view(), name='vlan_bulk_edit'),
     path('vlans/edit/', views.VLANBulkEditView.as_view(), name='vlan_bulk_edit'),
     path('vlans/delete/', views.VLANBulkDeleteView.as_view(), name='vlan_bulk_delete'),
     path('vlans/delete/', views.VLANBulkDeleteView.as_view(), name='vlan_bulk_delete'),
-    path('vlans/<int:pk>/', views.VLANView.as_view(), name='vlan'),
-    path('vlans/<int:pk>/edit/', views.VLANEditView.as_view(), name='vlan_edit'),
-    path('vlans/<int:pk>/delete/', views.VLANDeleteView.as_view(), name='vlan_delete'),
     path('vlans/<int:pk>/', include(get_model_urls('ipam', 'vlan'))),
     path('vlans/<int:pk>/', include(get_model_urls('ipam', 'vlan'))),
 
 
     # Service templates
     # Service templates
@@ -151,9 +114,6 @@ urlpatterns = [
     path('service-templates/import/', views.ServiceTemplateBulkImportView.as_view(), name='servicetemplate_import'),
     path('service-templates/import/', views.ServiceTemplateBulkImportView.as_view(), name='servicetemplate_import'),
     path('service-templates/edit/', views.ServiceTemplateBulkEditView.as_view(), name='servicetemplate_bulk_edit'),
     path('service-templates/edit/', views.ServiceTemplateBulkEditView.as_view(), name='servicetemplate_bulk_edit'),
     path('service-templates/delete/', views.ServiceTemplateBulkDeleteView.as_view(), name='servicetemplate_bulk_delete'),
     path('service-templates/delete/', views.ServiceTemplateBulkDeleteView.as_view(), name='servicetemplate_bulk_delete'),
-    path('service-templates/<int:pk>/', views.ServiceTemplateView.as_view(), name='servicetemplate'),
-    path('service-templates/<int:pk>/edit/', views.ServiceTemplateEditView.as_view(), name='servicetemplate_edit'),
-    path('service-templates/<int:pk>/delete/', views.ServiceTemplateDeleteView.as_view(), name='servicetemplate_delete'),
     path('service-templates/<int:pk>/', include(get_model_urls('ipam', 'servicetemplate'))),
     path('service-templates/<int:pk>/', include(get_model_urls('ipam', 'servicetemplate'))),
 
 
     # Services
     # Services
@@ -162,9 +122,6 @@ urlpatterns = [
     path('services/import/', views.ServiceBulkImportView.as_view(), name='service_import'),
     path('services/import/', views.ServiceBulkImportView.as_view(), name='service_import'),
     path('services/edit/', views.ServiceBulkEditView.as_view(), name='service_bulk_edit'),
     path('services/edit/', views.ServiceBulkEditView.as_view(), name='service_bulk_edit'),
     path('services/delete/', views.ServiceBulkDeleteView.as_view(), name='service_bulk_delete'),
     path('services/delete/', views.ServiceBulkDeleteView.as_view(), name='service_bulk_delete'),
-    path('services/<int:pk>/', views.ServiceView.as_view(), name='service'),
-    path('services/<int:pk>/edit/', views.ServiceEditView.as_view(), name='service_edit'),
-    path('services/<int:pk>/delete/', views.ServiceDeleteView.as_view(), name='service_delete'),
     path('services/<int:pk>/', include(get_model_urls('ipam', 'service'))),
     path('services/<int:pk>/', include(get_model_urls('ipam', 'service'))),
 
 
     # L2VPN
     # L2VPN
@@ -173,9 +130,6 @@ urlpatterns = [
     path('l2vpns/import/', views.L2VPNBulkImportView.as_view(), name='l2vpn_import'),
     path('l2vpns/import/', views.L2VPNBulkImportView.as_view(), name='l2vpn_import'),
     path('l2vpns/edit/', views.L2VPNBulkEditView.as_view(), name='l2vpn_bulk_edit'),
     path('l2vpns/edit/', views.L2VPNBulkEditView.as_view(), name='l2vpn_bulk_edit'),
     path('l2vpns/delete/', views.L2VPNBulkDeleteView.as_view(), name='l2vpn_bulk_delete'),
     path('l2vpns/delete/', views.L2VPNBulkDeleteView.as_view(), name='l2vpn_bulk_delete'),
-    path('l2vpns/<int:pk>/', views.L2VPNView.as_view(), name='l2vpn'),
-    path('l2vpns/<int:pk>/edit/', views.L2VPNEditView.as_view(), name='l2vpn_edit'),
-    path('l2vpns/<int:pk>/delete/', views.L2VPNDeleteView.as_view(), name='l2vpn_delete'),
     path('l2vpns/<int:pk>/', include(get_model_urls('ipam', 'l2vpn'))),
     path('l2vpns/<int:pk>/', include(get_model_urls('ipam', 'l2vpn'))),
 
 
     # L2VPN terminations
     # L2VPN terminations
@@ -184,8 +138,5 @@ urlpatterns = [
     path('l2vpn-terminations/import/', views.L2VPNTerminationBulkImportView.as_view(), name='l2vpntermination_import'),
     path('l2vpn-terminations/import/', views.L2VPNTerminationBulkImportView.as_view(), name='l2vpntermination_import'),
     path('l2vpn-terminations/edit/', views.L2VPNTerminationBulkEditView.as_view(), name='l2vpntermination_bulk_edit'),
     path('l2vpn-terminations/edit/', views.L2VPNTerminationBulkEditView.as_view(), name='l2vpntermination_bulk_edit'),
     path('l2vpn-terminations/delete/', views.L2VPNTerminationBulkDeleteView.as_view(), name='l2vpntermination_bulk_delete'),
     path('l2vpn-terminations/delete/', views.L2VPNTerminationBulkDeleteView.as_view(), name='l2vpntermination_bulk_delete'),
-    path('l2vpn-terminations/<int:pk>/', views.L2VPNTerminationView.as_view(), name='l2vpntermination'),
-    path('l2vpn-terminations/<int:pk>/edit/', views.L2VPNTerminationEditView.as_view(), name='l2vpntermination_edit'),
-    path('l2vpn-terminations/<int:pk>/delete/', views.L2VPNTerminationDeleteView.as_view(), name='l2vpntermination_delete'),
     path('l2vpn-terminations/<int:pk>/', include(get_model_urls('ipam', 'l2vpntermination'))),
     path('l2vpn-terminations/<int:pk>/', include(get_model_urls('ipam', 'l2vpntermination'))),
 ]
 ]

+ 54 - 1
netbox/ipam/views.py

@@ -34,6 +34,7 @@ class VRFListView(generic.ObjectListView):
     table = tables.VRFTable
     table = tables.VRFTable
 
 
 
 
+@register_model_view(VRF)
 class VRFView(generic.ObjectView):
 class VRFView(generic.ObjectView):
     queryset = VRF.objects.all()
     queryset = VRF.objects.all()
 
 
@@ -58,11 +59,13 @@ class VRFView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(VRF, 'edit')
 class VRFEditView(generic.ObjectEditView):
 class VRFEditView(generic.ObjectEditView):
     queryset = VRF.objects.all()
     queryset = VRF.objects.all()
     form = forms.VRFForm
     form = forms.VRFForm
 
 
 
 
+@register_model_view(VRF, 'delete')
 class VRFDeleteView(generic.ObjectDeleteView):
 class VRFDeleteView(generic.ObjectDeleteView):
     queryset = VRF.objects.all()
     queryset = VRF.objects.all()
 
 
@@ -97,6 +100,7 @@ class RouteTargetListView(generic.ObjectListView):
     table = tables.RouteTargetTable
     table = tables.RouteTargetTable
 
 
 
 
+@register_model_view(RouteTarget)
 class RouteTargetView(generic.ObjectView):
 class RouteTargetView(generic.ObjectView):
     queryset = RouteTarget.objects.all()
     queryset = RouteTarget.objects.all()
 
 
@@ -116,11 +120,13 @@ class RouteTargetView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(RouteTarget, 'edit')
 class RouteTargetEditView(generic.ObjectEditView):
 class RouteTargetEditView(generic.ObjectEditView):
     queryset = RouteTarget.objects.all()
     queryset = RouteTarget.objects.all()
     form = forms.RouteTargetForm
     form = forms.RouteTargetForm
 
 
 
 
+@register_model_view(RouteTarget, 'delete')
 class RouteTargetDeleteView(generic.ObjectDeleteView):
 class RouteTargetDeleteView(generic.ObjectDeleteView):
     queryset = RouteTarget.objects.all()
     queryset = RouteTarget.objects.all()
 
 
@@ -157,6 +163,7 @@ class RIRListView(generic.ObjectListView):
     table = tables.RIRTable
     table = tables.RIRTable
 
 
 
 
+@register_model_view(RIR)
 class RIRView(generic.ObjectView):
 class RIRView(generic.ObjectView):
     queryset = RIR.objects.all()
     queryset = RIR.objects.all()
 
 
@@ -172,11 +179,13 @@ class RIRView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(RIR, 'edit')
 class RIREditView(generic.ObjectEditView):
 class RIREditView(generic.ObjectEditView):
     queryset = RIR.objects.all()
     queryset = RIR.objects.all()
     form = forms.RIRForm
     form = forms.RIRForm
 
 
 
 
+@register_model_view(RIR, 'delete')
 class RIRDeleteView(generic.ObjectDeleteView):
 class RIRDeleteView(generic.ObjectDeleteView):
     queryset = RIR.objects.all()
     queryset = RIR.objects.all()
 
 
@@ -218,6 +227,7 @@ class ASNListView(generic.ObjectListView):
     table = tables.ASNTable
     table = tables.ASNTable
 
 
 
 
+@register_model_view(ASN)
 class ASNView(generic.ObjectView):
 class ASNView(generic.ObjectView):
     queryset = ASN.objects.all()
     queryset = ASN.objects.all()
 
 
@@ -242,11 +252,13 @@ class ASNView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(ASN, 'edit')
 class ASNEditView(generic.ObjectEditView):
 class ASNEditView(generic.ObjectEditView):
     queryset = ASN.objects.all()
     queryset = ASN.objects.all()
     form = forms.ASNForm
     form = forms.ASNForm
 
 
 
 
+@register_model_view(ASN, 'delete')
 class ASNDeleteView(generic.ObjectDeleteView):
 class ASNDeleteView(generic.ObjectDeleteView):
     queryset = ASN.objects.all()
     queryset = ASN.objects.all()
 
 
@@ -287,6 +299,7 @@ class AggregateListView(generic.ObjectListView):
     table = tables.AggregateTable
     table = tables.AggregateTable
 
 
 
 
+@register_model_view(Aggregate)
 class AggregateView(generic.ObjectView):
 class AggregateView(generic.ObjectView):
     queryset = Aggregate.objects.all()
     queryset = Aggregate.objects.all()
 
 
@@ -325,11 +338,13 @@ class AggregatePrefixesView(generic.ObjectChildrenView):
         }
         }
 
 
 
 
+@register_model_view(Aggregate, 'edit')
 class AggregateEditView(generic.ObjectEditView):
 class AggregateEditView(generic.ObjectEditView):
     queryset = Aggregate.objects.all()
     queryset = Aggregate.objects.all()
     form = forms.AggregateForm
     form = forms.AggregateForm
 
 
 
 
+@register_model_view(Aggregate, 'delete')
 class AggregateDeleteView(generic.ObjectDeleteView):
 class AggregateDeleteView(generic.ObjectDeleteView):
     queryset = Aggregate.objects.all()
     queryset = Aggregate.objects.all()
 
 
@@ -372,6 +387,7 @@ class RoleListView(generic.ObjectListView):
     table = tables.RoleTable
     table = tables.RoleTable
 
 
 
 
+@register_model_view(Role)
 class RoleView(generic.ObjectView):
 class RoleView(generic.ObjectView):
     queryset = Role.objects.all()
     queryset = Role.objects.all()
 
 
@@ -388,11 +404,13 @@ class RoleView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(Role, 'edit')
 class RoleEditView(generic.ObjectEditView):
 class RoleEditView(generic.ObjectEditView):
     queryset = Role.objects.all()
     queryset = Role.objects.all()
     form = forms.RoleForm
     form = forms.RoleForm
 
 
 
 
+@register_model_view(Role, 'delete')
 class RoleDeleteView(generic.ObjectDeleteView):
 class RoleDeleteView(generic.ObjectDeleteView):
     queryset = Role.objects.all()
     queryset = Role.objects.all()
 
 
@@ -427,6 +445,7 @@ class PrefixListView(generic.ObjectListView):
     template_name = 'ipam/prefix_list.html'
     template_name = 'ipam/prefix_list.html'
 
 
 
 
+@register_model_view(Prefix)
 class PrefixView(generic.ObjectView):
 class PrefixView(generic.ObjectView):
     queryset = Prefix.objects.all()
     queryset = Prefix.objects.all()
 
 
@@ -560,11 +579,13 @@ class PrefixIPAddressesView(generic.ObjectChildrenView):
         }
         }
 
 
 
 
+@register_model_view(Prefix, 'edit')
 class PrefixEditView(generic.ObjectEditView):
 class PrefixEditView(generic.ObjectEditView):
     queryset = Prefix.objects.all()
     queryset = Prefix.objects.all()
     form = forms.PrefixForm
     form = forms.PrefixForm
 
 
 
 
+@register_model_view(Prefix, 'delete')
 class PrefixDeleteView(generic.ObjectDeleteView):
 class PrefixDeleteView(generic.ObjectDeleteView):
     queryset = Prefix.objects.all()
     queryset = Prefix.objects.all()
 
 
@@ -599,6 +620,7 @@ class IPRangeListView(generic.ObjectListView):
     table = tables.IPRangeTable
     table = tables.IPRangeTable
 
 
 
 
+@register_model_view(IPRange)
 class IPRangeView(generic.ObjectView):
 class IPRangeView(generic.ObjectView):
     queryset = IPRange.objects.all()
     queryset = IPRange.objects.all()
 
 
@@ -620,11 +642,13 @@ class IPRangeIPAddressesView(generic.ObjectChildrenView):
         return parent.get_child_ips().restrict(request.user, 'view')
         return parent.get_child_ips().restrict(request.user, 'view')
 
 
 
 
+@register_model_view(IPRange, 'edit')
 class IPRangeEditView(generic.ObjectEditView):
 class IPRangeEditView(generic.ObjectEditView):
     queryset = IPRange.objects.all()
     queryset = IPRange.objects.all()
     form = forms.IPRangeForm
     form = forms.IPRangeForm
 
 
 
 
+@register_model_view(IPRange, 'delete')
 class IPRangeDeleteView(generic.ObjectDeleteView):
 class IPRangeDeleteView(generic.ObjectDeleteView):
     queryset = IPRange.objects.all()
     queryset = IPRange.objects.all()
 
 
@@ -659,6 +683,7 @@ class IPAddressListView(generic.ObjectListView):
     table = tables.IPAddressTable
     table = tables.IPAddressTable
 
 
 
 
+@register_model_view(IPAddress)
 class IPAddressView(generic.ObjectView):
 class IPAddressView(generic.ObjectView):
     queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant')
     queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant')
 
 
@@ -726,6 +751,7 @@ class IPAddressView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(IPAddress, 'edit')
 class IPAddressEditView(generic.ObjectEditView):
 class IPAddressEditView(generic.ObjectEditView):
     queryset = IPAddress.objects.all()
     queryset = IPAddress.objects.all()
     form = forms.IPAddressForm
     form = forms.IPAddressForm
@@ -795,6 +821,7 @@ class IPAddressAssignView(generic.ObjectView):
         })
         })
 
 
 
 
+@register_model_view(IPAddress, 'delete')
 class IPAddressDeleteView(generic.ObjectDeleteView):
 class IPAddressDeleteView(generic.ObjectDeleteView):
     queryset = IPAddress.objects.all()
     queryset = IPAddress.objects.all()
 
 
@@ -839,6 +866,7 @@ class VLANGroupListView(generic.ObjectListView):
     table = tables.VLANGroupTable
     table = tables.VLANGroupTable
 
 
 
 
+@register_model_view(VLANGroup)
 class VLANGroupView(generic.ObjectView):
 class VLANGroupView(generic.ObjectView):
     queryset = VLANGroup.objects.all()
     queryset = VLANGroup.objects.all()
 
 
@@ -869,11 +897,13 @@ class VLANGroupView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(VLANGroup, 'edit')
 class VLANGroupEditView(generic.ObjectEditView):
 class VLANGroupEditView(generic.ObjectEditView):
     queryset = VLANGroup.objects.all()
     queryset = VLANGroup.objects.all()
     form = forms.VLANGroupForm
     form = forms.VLANGroupForm
 
 
 
 
+@register_model_view(VLANGroup, 'delete')
 class VLANGroupDeleteView(generic.ObjectDeleteView):
 class VLANGroupDeleteView(generic.ObjectDeleteView):
     queryset = VLANGroup.objects.all()
     queryset = VLANGroup.objects.all()
 
 
@@ -914,6 +944,7 @@ class FHRPGroupListView(generic.ObjectListView):
     table = tables.FHRPGroupTable
     table = tables.FHRPGroupTable
 
 
 
 
+@register_model_view(FHRPGroup)
 class FHRPGroupView(generic.ObjectView):
 class FHRPGroupView(generic.ObjectView):
     queryset = FHRPGroup.objects.all()
     queryset = FHRPGroup.objects.all()
 
 
@@ -938,6 +969,7 @@ class FHRPGroupView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(FHRPGroup, 'edit')
 class FHRPGroupEditView(generic.ObjectEditView):
 class FHRPGroupEditView(generic.ObjectEditView):
     queryset = FHRPGroup.objects.all()
     queryset = FHRPGroup.objects.all()
     form = forms.FHRPGroupForm
     form = forms.FHRPGroupForm
@@ -954,6 +986,7 @@ class FHRPGroupEditView(generic.ObjectEditView):
         return return_url
         return return_url
 
 
 
 
+@register_model_view(FHRPGroup, 'delete')
 class FHRPGroupDeleteView(generic.ObjectDeleteView):
 class FHRPGroupDeleteView(generic.ObjectDeleteView):
     queryset = FHRPGroup.objects.all()
     queryset = FHRPGroup.objects.all()
 
 
@@ -981,6 +1014,7 @@ class FHRPGroupBulkDeleteView(generic.BulkDeleteView):
 # FHRP group assignments
 # FHRP group assignments
 #
 #
 
 
+@register_model_view(FHRPGroupAssignment, 'edit')
 class FHRPGroupAssignmentEditView(generic.ObjectEditView):
 class FHRPGroupAssignmentEditView(generic.ObjectEditView):
     queryset = FHRPGroupAssignment.objects.all()
     queryset = FHRPGroupAssignment.objects.all()
     form = forms.FHRPGroupAssignmentForm
     form = forms.FHRPGroupAssignmentForm
@@ -994,6 +1028,7 @@ class FHRPGroupAssignmentEditView(generic.ObjectEditView):
         return instance
         return instance
 
 
 
 
+@register_model_view(FHRPGroupAssignment, 'delete')
 class FHRPGroupAssignmentDeleteView(generic.ObjectDeleteView):
 class FHRPGroupAssignmentDeleteView(generic.ObjectDeleteView):
     queryset = FHRPGroupAssignment.objects.all()
     queryset = FHRPGroupAssignment.objects.all()
 
 
@@ -1009,6 +1044,7 @@ class VLANListView(generic.ObjectListView):
     table = tables.VLANTable
     table = tables.VLANTable
 
 
 
 
+@register_model_view(VLAN)
 class VLANView(generic.ObjectView):
 class VLANView(generic.ObjectView):
     queryset = VLAN.objects.all()
     queryset = VLAN.objects.all()
 
 
@@ -1057,12 +1093,14 @@ class VLANVMInterfacesView(generic.ObjectChildrenView):
         return parent.get_vminterfaces().restrict(request.user, 'view')
         return parent.get_vminterfaces().restrict(request.user, 'view')
 
 
 
 
+@register_model_view(VLAN, 'edit')
 class VLANEditView(generic.ObjectEditView):
 class VLANEditView(generic.ObjectEditView):
     queryset = VLAN.objects.all()
     queryset = VLAN.objects.all()
     form = forms.VLANForm
     form = forms.VLANForm
     template_name = 'ipam/vlan_edit.html'
     template_name = 'ipam/vlan_edit.html'
 
 
 
 
+@register_model_view(VLAN, 'delete')
 class VLANDeleteView(generic.ObjectDeleteView):
 class VLANDeleteView(generic.ObjectDeleteView):
     queryset = VLAN.objects.all()
     queryset = VLAN.objects.all()
 
 
@@ -1097,15 +1135,18 @@ class ServiceTemplateListView(generic.ObjectListView):
     table = tables.ServiceTemplateTable
     table = tables.ServiceTemplateTable
 
 
 
 
+@register_model_view(ServiceTemplate)
 class ServiceTemplateView(generic.ObjectView):
 class ServiceTemplateView(generic.ObjectView):
     queryset = ServiceTemplate.objects.all()
     queryset = ServiceTemplate.objects.all()
 
 
 
 
+@register_model_view(ServiceTemplate, 'edit')
 class ServiceTemplateEditView(generic.ObjectEditView):
 class ServiceTemplateEditView(generic.ObjectEditView):
     queryset = ServiceTemplate.objects.all()
     queryset = ServiceTemplate.objects.all()
     form = forms.ServiceTemplateForm
     form = forms.ServiceTemplateForm
 
 
 
 
+@register_model_view(ServiceTemplate, 'delete')
 class ServiceTemplateDeleteView(generic.ObjectDeleteView):
 class ServiceTemplateDeleteView(generic.ObjectDeleteView):
     queryset = ServiceTemplate.objects.all()
     queryset = ServiceTemplate.objects.all()
 
 
@@ -1140,6 +1181,7 @@ class ServiceListView(generic.ObjectListView):
     table = tables.ServiceTable
     table = tables.ServiceTable
 
 
 
 
+@register_model_view(Service)
 class ServiceView(generic.ObjectView):
 class ServiceView(generic.ObjectView):
     queryset = Service.objects.all()
     queryset = Service.objects.all()
 
 
@@ -1150,12 +1192,14 @@ class ServiceCreateView(generic.ObjectEditView):
     template_name = 'ipam/service_create.html'
     template_name = 'ipam/service_create.html'
 
 
 
 
+@register_model_view(Service, 'edit')
 class ServiceEditView(generic.ObjectEditView):
 class ServiceEditView(generic.ObjectEditView):
     queryset = Service.objects.all()
     queryset = Service.objects.all()
     form = forms.ServiceForm
     form = forms.ServiceForm
     template_name = 'ipam/service_edit.html'
     template_name = 'ipam/service_edit.html'
 
 
 
 
+@register_model_view(Service, 'delete')
 class ServiceDeleteView(generic.ObjectDeleteView):
 class ServiceDeleteView(generic.ObjectDeleteView):
     queryset = Service.objects.all()
     queryset = Service.objects.all()
 
 
@@ -1181,7 +1225,6 @@ class ServiceBulkDeleteView(generic.BulkDeleteView):
 
 
 # L2VPN
 # L2VPN
 
 
-
 class L2VPNListView(generic.ObjectListView):
 class L2VPNListView(generic.ObjectListView):
     queryset = L2VPN.objects.all()
     queryset = L2VPN.objects.all()
     table = L2VPNTable
     table = L2VPNTable
@@ -1189,6 +1232,7 @@ class L2VPNListView(generic.ObjectListView):
     filterset_form = forms.L2VPNFilterForm
     filterset_form = forms.L2VPNFilterForm
 
 
 
 
+@register_model_view(L2VPN)
 class L2VPNView(generic.ObjectView):
 class L2VPNView(generic.ObjectView):
     queryset = L2VPN.objects.all()
     queryset = L2VPN.objects.all()
 
 
@@ -1213,11 +1257,13 @@ class L2VPNView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(L2VPN, 'edit')
 class L2VPNEditView(generic.ObjectEditView):
 class L2VPNEditView(generic.ObjectEditView):
     queryset = L2VPN.objects.all()
     queryset = L2VPN.objects.all()
     form = forms.L2VPNForm
     form = forms.L2VPNForm
 
 
 
 
+@register_model_view(L2VPN, 'delete')
 class L2VPNDeleteView(generic.ObjectDeleteView):
 class L2VPNDeleteView(generic.ObjectDeleteView):
     queryset = L2VPN.objects.all()
     queryset = L2VPN.objects.all()
 
 
@@ -1241,6 +1287,10 @@ class L2VPNBulkDeleteView(generic.BulkDeleteView):
     table = tables.L2VPNTable
     table = tables.L2VPNTable
 
 
 
 
+#
+# L2VPN terminations
+#
+
 class L2VPNTerminationListView(generic.ObjectListView):
 class L2VPNTerminationListView(generic.ObjectListView):
     queryset = L2VPNTermination.objects.all()
     queryset = L2VPNTermination.objects.all()
     table = L2VPNTerminationTable
     table = L2VPNTerminationTable
@@ -1248,16 +1298,19 @@ class L2VPNTerminationListView(generic.ObjectListView):
     filterset_form = forms.L2VPNTerminationFilterForm
     filterset_form = forms.L2VPNTerminationFilterForm
 
 
 
 
+@register_model_view(L2VPNTermination)
 class L2VPNTerminationView(generic.ObjectView):
 class L2VPNTerminationView(generic.ObjectView):
     queryset = L2VPNTermination.objects.all()
     queryset = L2VPNTermination.objects.all()
 
 
 
 
+@register_model_view(L2VPNTermination, 'edit')
 class L2VPNTerminationEditView(generic.ObjectEditView):
 class L2VPNTerminationEditView(generic.ObjectEditView):
     queryset = L2VPNTermination.objects.all()
     queryset = L2VPNTermination.objects.all()
     form = forms.L2VPNTerminationForm
     form = forms.L2VPNTerminationForm
     template_name = 'ipam/l2vpntermination_edit.html'
     template_name = 'ipam/l2vpntermination_edit.html'
 
 
 
 
+@register_model_view(L2VPNTermination, 'delete')
 class L2VPNTerminationDeleteView(generic.ObjectDeleteView):
 class L2VPNTerminationDeleteView(generic.ObjectDeleteView):
     queryset = L2VPNTermination.objects.all()
     queryset = L2VPNTermination.objects.all()
 
 

+ 1 - 17
netbox/tenancy/urls.py

@@ -12,9 +12,6 @@ urlpatterns = [
     path('tenant-groups/import/', views.TenantGroupBulkImportView.as_view(), name='tenantgroup_import'),
     path('tenant-groups/import/', views.TenantGroupBulkImportView.as_view(), name='tenantgroup_import'),
     path('tenant-groups/edit/', views.TenantGroupBulkEditView.as_view(), name='tenantgroup_bulk_edit'),
     path('tenant-groups/edit/', views.TenantGroupBulkEditView.as_view(), name='tenantgroup_bulk_edit'),
     path('tenant-groups/delete/', views.TenantGroupBulkDeleteView.as_view(), name='tenantgroup_bulk_delete'),
     path('tenant-groups/delete/', views.TenantGroupBulkDeleteView.as_view(), name='tenantgroup_bulk_delete'),
-    path('tenant-groups/<int:pk>/', views.TenantGroupView.as_view(), name='tenantgroup'),
-    path('tenant-groups/<int:pk>/edit/', views.TenantGroupEditView.as_view(), name='tenantgroup_edit'),
-    path('tenant-groups/<int:pk>/delete/', views.TenantGroupDeleteView.as_view(), name='tenantgroup_delete'),
     path('tenant-groups/<int:pk>/', include(get_model_urls('tenancy', 'tenantgroup'))),
     path('tenant-groups/<int:pk>/', include(get_model_urls('tenancy', 'tenantgroup'))),
 
 
     # Tenants
     # Tenants
@@ -23,9 +20,6 @@ urlpatterns = [
     path('tenants/import/', views.TenantBulkImportView.as_view(), name='tenant_import'),
     path('tenants/import/', views.TenantBulkImportView.as_view(), name='tenant_import'),
     path('tenants/edit/', views.TenantBulkEditView.as_view(), name='tenant_bulk_edit'),
     path('tenants/edit/', views.TenantBulkEditView.as_view(), name='tenant_bulk_edit'),
     path('tenants/delete/', views.TenantBulkDeleteView.as_view(), name='tenant_bulk_delete'),
     path('tenants/delete/', views.TenantBulkDeleteView.as_view(), name='tenant_bulk_delete'),
-    path('tenants/<int:pk>/', views.TenantView.as_view(), name='tenant'),
-    path('tenants/<int:pk>/edit/', views.TenantEditView.as_view(), name='tenant_edit'),
-    path('tenants/<int:pk>/delete/', views.TenantDeleteView.as_view(), name='tenant_delete'),
     path('tenants/<int:pk>/', include(get_model_urls('tenancy', 'tenant'))),
     path('tenants/<int:pk>/', include(get_model_urls('tenancy', 'tenant'))),
 
 
     # Contact groups
     # Contact groups
@@ -34,9 +28,6 @@ urlpatterns = [
     path('contact-groups/import/', views.ContactGroupBulkImportView.as_view(), name='contactgroup_import'),
     path('contact-groups/import/', views.ContactGroupBulkImportView.as_view(), name='contactgroup_import'),
     path('contact-groups/edit/', views.ContactGroupBulkEditView.as_view(), name='contactgroup_bulk_edit'),
     path('contact-groups/edit/', views.ContactGroupBulkEditView.as_view(), name='contactgroup_bulk_edit'),
     path('contact-groups/delete/', views.ContactGroupBulkDeleteView.as_view(), name='contactgroup_bulk_delete'),
     path('contact-groups/delete/', views.ContactGroupBulkDeleteView.as_view(), name='contactgroup_bulk_delete'),
-    path('contact-groups/<int:pk>/', views.ContactGroupView.as_view(), name='contactgroup'),
-    path('contact-groups/<int:pk>/edit/', views.ContactGroupEditView.as_view(), name='contactgroup_edit'),
-    path('contact-groups/<int:pk>/delete/', views.ContactGroupDeleteView.as_view(), name='contactgroup_delete'),
     path('contact-groups/<int:pk>/', include(get_model_urls('tenancy', 'contactgroup'))),
     path('contact-groups/<int:pk>/', include(get_model_urls('tenancy', 'contactgroup'))),
 
 
     # Contact roles
     # Contact roles
@@ -45,9 +36,6 @@ urlpatterns = [
     path('contact-roles/import/', views.ContactRoleBulkImportView.as_view(), name='contactrole_import'),
     path('contact-roles/import/', views.ContactRoleBulkImportView.as_view(), name='contactrole_import'),
     path('contact-roles/edit/', views.ContactRoleBulkEditView.as_view(), name='contactrole_bulk_edit'),
     path('contact-roles/edit/', views.ContactRoleBulkEditView.as_view(), name='contactrole_bulk_edit'),
     path('contact-roles/delete/', views.ContactRoleBulkDeleteView.as_view(), name='contactrole_bulk_delete'),
     path('contact-roles/delete/', views.ContactRoleBulkDeleteView.as_view(), name='contactrole_bulk_delete'),
-    path('contact-roles/<int:pk>/', views.ContactRoleView.as_view(), name='contactrole'),
-    path('contact-roles/<int:pk>/edit/', views.ContactRoleEditView.as_view(), name='contactrole_edit'),
-    path('contact-roles/<int:pk>/delete/', views.ContactRoleDeleteView.as_view(), name='contactrole_delete'),
     path('contact-roles/<int:pk>/', include(get_model_urls('tenancy', 'contactrole'))),
     path('contact-roles/<int:pk>/', include(get_model_urls('tenancy', 'contactrole'))),
 
 
     # Contacts
     # Contacts
@@ -56,14 +44,10 @@ urlpatterns = [
     path('contacts/import/', views.ContactBulkImportView.as_view(), name='contact_import'),
     path('contacts/import/', views.ContactBulkImportView.as_view(), name='contact_import'),
     path('contacts/edit/', views.ContactBulkEditView.as_view(), name='contact_bulk_edit'),
     path('contacts/edit/', views.ContactBulkEditView.as_view(), name='contact_bulk_edit'),
     path('contacts/delete/', views.ContactBulkDeleteView.as_view(), name='contact_bulk_delete'),
     path('contacts/delete/', views.ContactBulkDeleteView.as_view(), name='contact_bulk_delete'),
-    path('contacts/<int:pk>/', views.ContactView.as_view(), name='contact'),
-    path('contacts/<int:pk>/edit/', views.ContactEditView.as_view(), name='contact_edit'),
-    path('contacts/<int:pk>/delete/', views.ContactDeleteView.as_view(), name='contact_delete'),
     path('contacts/<int:pk>/', include(get_model_urls('tenancy', 'contact'))),
     path('contacts/<int:pk>/', include(get_model_urls('tenancy', 'contact'))),
 
 
     # Contact assignments
     # Contact assignments
     path('contact-assignments/add/', views.ContactAssignmentEditView.as_view(), name='contactassignment_add'),
     path('contact-assignments/add/', views.ContactAssignmentEditView.as_view(), name='contactassignment_add'),
-    path('contact-assignments/<int:pk>/edit/', views.ContactAssignmentEditView.as_view(), name='contactassignment_edit'),
-    path('contact-assignments/<int:pk>/delete/', views.ContactAssignmentDeleteView.as_view(), name='contactassignment_delete'),
+    path('contact-assignments/<int:pk>/', include(get_model_urls('tenancy', 'contactassignment'))),
 
 
 ]
 ]

+ 18 - 1
netbox/tenancy/views.py

@@ -1,5 +1,4 @@
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.models import ContentType
-from django.http import QueryDict
 from django.shortcuts import get_object_or_404
 from django.shortcuts import get_object_or_404
 
 
 from circuits.models import Circuit
 from circuits.models import Circuit
@@ -7,6 +6,7 @@ from dcim.models import Cable, Device, Location, Rack, RackReservation, Site
 from ipam.models import Aggregate, IPAddress, IPRange, Prefix, VLAN, VRF, ASN
 from ipam.models import Aggregate, IPAddress, IPRange, Prefix, VLAN, VRF, ASN
 from netbox.views import generic
 from netbox.views import generic
 from utilities.utils import count_related
 from utilities.utils import count_related
+from utilities.views import register_model_view
 from virtualization.models import VirtualMachine, Cluster
 from virtualization.models import VirtualMachine, Cluster
 from wireless.models import WirelessLAN, WirelessLink
 from wireless.models import WirelessLAN, WirelessLink
 from . import filtersets, forms, tables
 from . import filtersets, forms, tables
@@ -30,6 +30,7 @@ class TenantGroupListView(generic.ObjectListView):
     table = tables.TenantGroupTable
     table = tables.TenantGroupTable
 
 
 
 
+@register_model_view(TenantGroup)
 class TenantGroupView(generic.ObjectView):
 class TenantGroupView(generic.ObjectView):
     queryset = TenantGroup.objects.all()
     queryset = TenantGroup.objects.all()
 
 
@@ -45,11 +46,13 @@ class TenantGroupView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(TenantGroup, 'edit')
 class TenantGroupEditView(generic.ObjectEditView):
 class TenantGroupEditView(generic.ObjectEditView):
     queryset = TenantGroup.objects.all()
     queryset = TenantGroup.objects.all()
     form = forms.TenantGroupForm
     form = forms.TenantGroupForm
 
 
 
 
+@register_model_view(TenantGroup, 'delete')
 class TenantGroupDeleteView(generic.ObjectDeleteView):
 class TenantGroupDeleteView(generic.ObjectDeleteView):
     queryset = TenantGroup.objects.all()
     queryset = TenantGroup.objects.all()
 
 
@@ -95,6 +98,7 @@ class TenantListView(generic.ObjectListView):
     table = tables.TenantTable
     table = tables.TenantTable
 
 
 
 
+@register_model_view(Tenant)
 class TenantView(generic.ObjectView):
 class TenantView(generic.ObjectView):
     queryset = Tenant.objects.all()
     queryset = Tenant.objects.all()
 
 
@@ -125,11 +129,13 @@ class TenantView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(Tenant, 'edit')
 class TenantEditView(generic.ObjectEditView):
 class TenantEditView(generic.ObjectEditView):
     queryset = Tenant.objects.all()
     queryset = Tenant.objects.all()
     form = forms.TenantForm
     form = forms.TenantForm
 
 
 
 
+@register_model_view(Tenant, 'delete')
 class TenantDeleteView(generic.ObjectDeleteView):
 class TenantDeleteView(generic.ObjectDeleteView):
     queryset = Tenant.objects.all()
     queryset = Tenant.objects.all()
 
 
@@ -170,6 +176,7 @@ class ContactGroupListView(generic.ObjectListView):
     table = tables.ContactGroupTable
     table = tables.ContactGroupTable
 
 
 
 
+@register_model_view(ContactGroup)
 class ContactGroupView(generic.ObjectView):
 class ContactGroupView(generic.ObjectView):
     queryset = ContactGroup.objects.all()
     queryset = ContactGroup.objects.all()
 
 
@@ -198,11 +205,13 @@ class ContactGroupView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(ContactGroup, 'edit')
 class ContactGroupEditView(generic.ObjectEditView):
 class ContactGroupEditView(generic.ObjectEditView):
     queryset = ContactGroup.objects.all()
     queryset = ContactGroup.objects.all()
     form = forms.ContactGroupForm
     form = forms.ContactGroupForm
 
 
 
 
+@register_model_view(ContactGroup, 'delete')
 class ContactGroupDeleteView(generic.ObjectDeleteView):
 class ContactGroupDeleteView(generic.ObjectDeleteView):
     queryset = ContactGroup.objects.all()
     queryset = ContactGroup.objects.all()
 
 
@@ -248,6 +257,7 @@ class ContactRoleListView(generic.ObjectListView):
     table = tables.ContactRoleTable
     table = tables.ContactRoleTable
 
 
 
 
+@register_model_view(ContactRole)
 class ContactRoleView(generic.ObjectView):
 class ContactRoleView(generic.ObjectView):
     queryset = ContactRole.objects.all()
     queryset = ContactRole.objects.all()
 
 
@@ -265,11 +275,13 @@ class ContactRoleView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(ContactRole, 'edit')
 class ContactRoleEditView(generic.ObjectEditView):
 class ContactRoleEditView(generic.ObjectEditView):
     queryset = ContactRole.objects.all()
     queryset = ContactRole.objects.all()
     form = forms.ContactRoleForm
     form = forms.ContactRoleForm
 
 
 
 
+@register_model_view(ContactRole, 'delete')
 class ContactRoleDeleteView(generic.ObjectDeleteView):
 class ContactRoleDeleteView(generic.ObjectDeleteView):
     queryset = ContactRole.objects.all()
     queryset = ContactRole.objects.all()
 
 
@@ -305,6 +317,7 @@ class ContactListView(generic.ObjectListView):
     table = tables.ContactTable
     table = tables.ContactTable
 
 
 
 
+@register_model_view(Contact)
 class ContactView(generic.ObjectView):
 class ContactView(generic.ObjectView):
     queryset = Contact.objects.all()
     queryset = Contact.objects.all()
 
 
@@ -322,11 +335,13 @@ class ContactView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(Contact, 'edit')
 class ContactEditView(generic.ObjectEditView):
 class ContactEditView(generic.ObjectEditView):
     queryset = Contact.objects.all()
     queryset = Contact.objects.all()
     form = forms.ContactForm
     form = forms.ContactForm
 
 
 
 
+@register_model_view(Contact, 'delete')
 class ContactDeleteView(generic.ObjectDeleteView):
 class ContactDeleteView(generic.ObjectDeleteView):
     queryset = Contact.objects.all()
     queryset = Contact.objects.all()
 
 
@@ -354,6 +369,7 @@ class ContactBulkDeleteView(generic.BulkDeleteView):
 # Contact assignments
 # Contact assignments
 #
 #
 
 
+@register_model_view(ContactAssignment, 'edit')
 class ContactAssignmentEditView(generic.ObjectEditView):
 class ContactAssignmentEditView(generic.ObjectEditView):
     queryset = ContactAssignment.objects.all()
     queryset = ContactAssignment.objects.all()
     form = forms.ContactAssignmentForm
     form = forms.ContactAssignmentForm
@@ -373,5 +389,6 @@ class ContactAssignmentEditView(generic.ObjectEditView):
         }
         }
 
 
 
 
+@register_model_view(ContactAssignment, 'delete')
 class ContactAssignmentDeleteView(generic.ObjectDeleteView):
 class ContactAssignmentDeleteView(generic.ObjectDeleteView):
     queryset = ContactAssignment.objects.all()
     queryset = ContactAssignment.objects.all()

+ 3 - 1
netbox/utilities/urls.py

@@ -32,8 +32,10 @@ def get_model_urls(app_label, model_name):
             view_ = view_.as_view()
             view_ = view_.as_view()
 
 
         # Create a path to the view
         # Create a path to the view
+        name = f"{model_name}_{config['name']}" if config['name'] else model_name
+        url_path = f"{config['path']}/" if config['path'] else ''
         paths.append(
         paths.append(
-            path(f"{config['path']}/", view_, name=f"{model_name}_{config['name']}", kwargs=config['kwargs'])
+            path(url_path, view_, name=name, kwargs=config['kwargs'])
         )
         )
 
 
     return paths
     return paths

+ 2 - 2
netbox/utilities/views.py

@@ -167,7 +167,7 @@ class ViewTab:
         return self.badge
         return self.badge
 
 
 
 
-def register_model_view(model, name, path=None, kwargs=None):
+def register_model_view(model, name='', path=None, kwargs=None):
     """
     """
     This decorator can be used to "attach" a view to any model in NetBox. This is typically used to inject
     This decorator can be used to "attach" a view to any model in NetBox. This is typically used to inject
     additional tabs within a model's detail view. For example, to add a custom tab to NetBox's dcim.Site model:
     additional tabs within a model's detail view. For example, to add a custom tab to NetBox's dcim.Site model:
@@ -182,7 +182,7 @@ def register_model_view(model, name, path=None, kwargs=None):
     Args:
     Args:
         model: The Django model class with which this view will be associated.
         model: The Django model class with which this view will be associated.
         name: The string used to form the view's name for URL resolution (e.g. via `reverse()`). This will be appended
         name: The string used to form the view's name for URL resolution (e.g. via `reverse()`). This will be appended
-            to the name of the base view for the model using an underscore.
+            to the name of the base view for the model using an underscore. If blank, the model name will be used.
         path: The URL path by which the view can be reached (optional). If not provided, `name` will be used.
         path: The URL path by which the view can be reached (optional). If not provided, `name` will be used.
         kwargs: A dictionary of keyword arguments for the view to include when registering its URL path (optional).
         kwargs: A dictionary of keyword arguments for the view to include when registering its URL path (optional).
     """
     """

+ 0 - 17
netbox/virtualization/urls.py

@@ -12,9 +12,6 @@ urlpatterns = [
     path('cluster-types/import/', views.ClusterTypeBulkImportView.as_view(), name='clustertype_import'),
     path('cluster-types/import/', views.ClusterTypeBulkImportView.as_view(), name='clustertype_import'),
     path('cluster-types/edit/', views.ClusterTypeBulkEditView.as_view(), name='clustertype_bulk_edit'),
     path('cluster-types/edit/', views.ClusterTypeBulkEditView.as_view(), name='clustertype_bulk_edit'),
     path('cluster-types/delete/', views.ClusterTypeBulkDeleteView.as_view(), name='clustertype_bulk_delete'),
     path('cluster-types/delete/', views.ClusterTypeBulkDeleteView.as_view(), name='clustertype_bulk_delete'),
-    path('cluster-types/<int:pk>/', views.ClusterTypeView.as_view(), name='clustertype'),
-    path('cluster-types/<int:pk>/edit/', views.ClusterTypeEditView.as_view(), name='clustertype_edit'),
-    path('cluster-types/<int:pk>/delete/', views.ClusterTypeDeleteView.as_view(), name='clustertype_delete'),
     path('cluster-types/<int:pk>/', include(get_model_urls('virtualization', 'clustertype'))),
     path('cluster-types/<int:pk>/', include(get_model_urls('virtualization', 'clustertype'))),
 
 
     # Cluster groups
     # Cluster groups
@@ -23,9 +20,6 @@ urlpatterns = [
     path('cluster-groups/import/', views.ClusterGroupBulkImportView.as_view(), name='clustergroup_import'),
     path('cluster-groups/import/', views.ClusterGroupBulkImportView.as_view(), name='clustergroup_import'),
     path('cluster-groups/edit/', views.ClusterGroupBulkEditView.as_view(), name='clustergroup_bulk_edit'),
     path('cluster-groups/edit/', views.ClusterGroupBulkEditView.as_view(), name='clustergroup_bulk_edit'),
     path('cluster-groups/delete/', views.ClusterGroupBulkDeleteView.as_view(), name='clustergroup_bulk_delete'),
     path('cluster-groups/delete/', views.ClusterGroupBulkDeleteView.as_view(), name='clustergroup_bulk_delete'),
-    path('cluster-groups/<int:pk>/', views.ClusterGroupView.as_view(), name='clustergroup'),
-    path('cluster-groups/<int:pk>/edit/', views.ClusterGroupEditView.as_view(), name='clustergroup_edit'),
-    path('cluster-groups/<int:pk>/delete/', views.ClusterGroupDeleteView.as_view(), name='clustergroup_delete'),
     path('cluster-groups/<int:pk>/', include(get_model_urls('virtualization', 'clustergroup'))),
     path('cluster-groups/<int:pk>/', include(get_model_urls('virtualization', 'clustergroup'))),
 
 
     # Clusters
     # Clusters
@@ -34,11 +28,6 @@ urlpatterns = [
     path('clusters/import/', views.ClusterBulkImportView.as_view(), name='cluster_import'),
     path('clusters/import/', views.ClusterBulkImportView.as_view(), name='cluster_import'),
     path('clusters/edit/', views.ClusterBulkEditView.as_view(), name='cluster_bulk_edit'),
     path('clusters/edit/', views.ClusterBulkEditView.as_view(), name='cluster_bulk_edit'),
     path('clusters/delete/', views.ClusterBulkDeleteView.as_view(), name='cluster_bulk_delete'),
     path('clusters/delete/', views.ClusterBulkDeleteView.as_view(), name='cluster_bulk_delete'),
-    path('clusters/<int:pk>/', views.ClusterView.as_view(), name='cluster'),
-    path('clusters/<int:pk>/edit/', views.ClusterEditView.as_view(), name='cluster_edit'),
-    path('clusters/<int:pk>/delete/', views.ClusterDeleteView.as_view(), name='cluster_delete'),
-    path('clusters/<int:pk>/devices/add/', views.ClusterAddDevicesView.as_view(), name='cluster_add_devices'),
-    path('clusters/<int:pk>/devices/remove/', views.ClusterRemoveDevicesView.as_view(), name='cluster_remove_devices'),
     path('clusters/<int:pk>/', include(get_model_urls('virtualization', 'cluster'))),
     path('clusters/<int:pk>/', include(get_model_urls('virtualization', 'cluster'))),
 
 
     # Virtual machines
     # Virtual machines
@@ -47,9 +36,6 @@ urlpatterns = [
     path('virtual-machines/import/', views.VirtualMachineBulkImportView.as_view(), name='virtualmachine_import'),
     path('virtual-machines/import/', views.VirtualMachineBulkImportView.as_view(), name='virtualmachine_import'),
     path('virtual-machines/edit/', views.VirtualMachineBulkEditView.as_view(), name='virtualmachine_bulk_edit'),
     path('virtual-machines/edit/', views.VirtualMachineBulkEditView.as_view(), name='virtualmachine_bulk_edit'),
     path('virtual-machines/delete/', views.VirtualMachineBulkDeleteView.as_view(), name='virtualmachine_bulk_delete'),
     path('virtual-machines/delete/', views.VirtualMachineBulkDeleteView.as_view(), name='virtualmachine_bulk_delete'),
-    path('virtual-machines/<int:pk>/', views.VirtualMachineView.as_view(), name='virtualmachine'),
-    path('virtual-machines/<int:pk>/edit/', views.VirtualMachineEditView.as_view(), name='virtualmachine_edit'),
-    path('virtual-machines/<int:pk>/delete/', views.VirtualMachineDeleteView.as_view(), name='virtualmachine_delete'),
     path('virtual-machines/<int:pk>/', include(get_model_urls('virtualization', 'virtualmachine'))),
     path('virtual-machines/<int:pk>/', include(get_model_urls('virtualization', 'virtualmachine'))),
 
 
     # VM interfaces
     # VM interfaces
@@ -59,9 +45,6 @@ urlpatterns = [
     path('interfaces/edit/', views.VMInterfaceBulkEditView.as_view(), name='vminterface_bulk_edit'),
     path('interfaces/edit/', views.VMInterfaceBulkEditView.as_view(), name='vminterface_bulk_edit'),
     path('interfaces/rename/', views.VMInterfaceBulkRenameView.as_view(), name='vminterface_bulk_rename'),
     path('interfaces/rename/', views.VMInterfaceBulkRenameView.as_view(), name='vminterface_bulk_rename'),
     path('interfaces/delete/', views.VMInterfaceBulkDeleteView.as_view(), name='vminterface_bulk_delete'),
     path('interfaces/delete/', views.VMInterfaceBulkDeleteView.as_view(), name='vminterface_bulk_delete'),
-    path('interfaces/<int:pk>/', views.VMInterfaceView.as_view(), name='vminterface'),
-    path('interfaces/<int:pk>/edit/', views.VMInterfaceEditView.as_view(), name='vminterface_edit'),
-    path('interfaces/<int:pk>/delete/', views.VMInterfaceDeleteView.as_view(), name='vminterface_delete'),
     path('interfaces/<int:pk>/', include(get_model_urls('virtualization', 'vminterface'))),
     path('interfaces/<int:pk>/', include(get_model_urls('virtualization', 'vminterface'))),
     path('virtual-machines/interfaces/add/', views.VirtualMachineBulkAddInterfaceView.as_view(), name='virtualmachine_bulk_add_vminterface'),
     path('virtual-machines/interfaces/add/', views.VirtualMachineBulkAddInterfaceView.as_view(), name='virtualmachine_bulk_add_vminterface'),
 
 

+ 17 - 0
netbox/virtualization/views.py

@@ -31,6 +31,7 @@ class ClusterTypeListView(generic.ObjectListView):
     table = tables.ClusterTypeTable
     table = tables.ClusterTypeTable
 
 
 
 
+@register_model_view(ClusterType)
 class ClusterTypeView(generic.ObjectView):
 class ClusterTypeView(generic.ObjectView):
     queryset = ClusterType.objects.all()
     queryset = ClusterType.objects.all()
 
 
@@ -49,11 +50,13 @@ class ClusterTypeView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(ClusterType, 'edit')
 class ClusterTypeEditView(generic.ObjectEditView):
 class ClusterTypeEditView(generic.ObjectEditView):
     queryset = ClusterType.objects.all()
     queryset = ClusterType.objects.all()
     form = forms.ClusterTypeForm
     form = forms.ClusterTypeForm
 
 
 
 
+@register_model_view(ClusterType, 'delete')
 class ClusterTypeDeleteView(generic.ObjectDeleteView):
 class ClusterTypeDeleteView(generic.ObjectDeleteView):
     queryset = ClusterType.objects.all()
     queryset = ClusterType.objects.all()
 
 
@@ -93,6 +96,7 @@ class ClusterGroupListView(generic.ObjectListView):
     table = tables.ClusterGroupTable
     table = tables.ClusterGroupTable
 
 
 
 
+@register_model_view(ClusterGroup)
 class ClusterGroupView(generic.ObjectView):
 class ClusterGroupView(generic.ObjectView):
     queryset = ClusterGroup.objects.all()
     queryset = ClusterGroup.objects.all()
 
 
@@ -111,11 +115,13 @@ class ClusterGroupView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(ClusterGroup, 'edit')
 class ClusterGroupEditView(generic.ObjectEditView):
 class ClusterGroupEditView(generic.ObjectEditView):
     queryset = ClusterGroup.objects.all()
     queryset = ClusterGroup.objects.all()
     form = forms.ClusterGroupForm
     form = forms.ClusterGroupForm
 
 
 
 
+@register_model_view(ClusterGroup, 'delete')
 class ClusterGroupDeleteView(generic.ObjectDeleteView):
 class ClusterGroupDeleteView(generic.ObjectDeleteView):
     queryset = ClusterGroup.objects.all()
     queryset = ClusterGroup.objects.all()
 
 
@@ -159,6 +165,7 @@ class ClusterListView(generic.ObjectListView):
     filterset_form = forms.ClusterFilterForm
     filterset_form = forms.ClusterFilterForm
 
 
 
 
+@register_model_view(Cluster)
 class ClusterView(generic.ObjectView):
 class ClusterView(generic.ObjectView):
     queryset = Cluster.objects.all()
     queryset = Cluster.objects.all()
 
 
@@ -197,11 +204,13 @@ class ClusterDevicesView(generic.ObjectChildrenView):
         return Device.objects.restrict(request.user, 'view').filter(cluster=parent)
         return Device.objects.restrict(request.user, 'view').filter(cluster=parent)
 
 
 
 
+@register_model_view(Cluster, 'edit')
 class ClusterEditView(generic.ObjectEditView):
 class ClusterEditView(generic.ObjectEditView):
     queryset = Cluster.objects.all()
     queryset = Cluster.objects.all()
     form = forms.ClusterForm
     form = forms.ClusterForm
 
 
 
 
+@register_model_view(Cluster, 'delete')
 class ClusterDeleteView(generic.ObjectDeleteView):
 class ClusterDeleteView(generic.ObjectDeleteView):
     queryset = Cluster.objects.all()
     queryset = Cluster.objects.all()
 
 
@@ -225,6 +234,7 @@ class ClusterBulkDeleteView(generic.BulkDeleteView):
     table = tables.ClusterTable
     table = tables.ClusterTable
 
 
 
 
+@register_model_view(Cluster, 'add_devices', path='devices/add')
 class ClusterAddDevicesView(generic.ObjectEditView):
 class ClusterAddDevicesView(generic.ObjectEditView):
     queryset = Cluster.objects.all()
     queryset = Cluster.objects.all()
     form = forms.ClusterAddDevicesForm
     form = forms.ClusterAddDevicesForm
@@ -266,6 +276,7 @@ class ClusterAddDevicesView(generic.ObjectEditView):
         })
         })
 
 
 
 
+@register_model_view(Cluster, 'remove_devices', path='devices/remove')
 class ClusterRemoveDevicesView(generic.ObjectEditView):
 class ClusterRemoveDevicesView(generic.ObjectEditView):
     queryset = Cluster.objects.all()
     queryset = Cluster.objects.all()
     form = forms.ClusterRemoveDevicesForm
     form = forms.ClusterRemoveDevicesForm
@@ -319,6 +330,7 @@ class VirtualMachineListView(generic.ObjectListView):
     template_name = 'virtualization/virtualmachine_list.html'
     template_name = 'virtualization/virtualmachine_list.html'
 
 
 
 
+@register_model_view(VirtualMachine)
 class VirtualMachineView(generic.ObjectView):
 class VirtualMachineView(generic.ObjectView):
     queryset = VirtualMachine.objects.prefetch_related('tenant__group')
     queryset = VirtualMachine.objects.prefetch_related('tenant__group')
 
 
@@ -378,11 +390,13 @@ class VirtualMachineConfigContextView(ObjectConfigContextView):
     )
     )
 
 
 
 
+@register_model_view(VirtualMachine, 'edit')
 class VirtualMachineEditView(generic.ObjectEditView):
 class VirtualMachineEditView(generic.ObjectEditView):
     queryset = VirtualMachine.objects.all()
     queryset = VirtualMachine.objects.all()
     form = forms.VirtualMachineForm
     form = forms.VirtualMachineForm
 
 
 
 
+@register_model_view(VirtualMachine, 'delete')
 class VirtualMachineDeleteView(generic.ObjectDeleteView):
 class VirtualMachineDeleteView(generic.ObjectDeleteView):
     queryset = VirtualMachine.objects.all()
     queryset = VirtualMachine.objects.all()
 
 
@@ -418,6 +432,7 @@ class VMInterfaceListView(generic.ObjectListView):
     actions = ('import', 'export', 'bulk_edit', 'bulk_delete')
     actions = ('import', 'export', 'bulk_edit', 'bulk_delete')
 
 
 
 
+@register_model_view(VMInterface)
 class VMInterfaceView(generic.ObjectView):
 class VMInterfaceView(generic.ObjectView):
     queryset = VMInterface.objects.all()
     queryset = VMInterface.objects.all()
 
 
@@ -463,11 +478,13 @@ class VMInterfaceCreateView(generic.ComponentCreateView):
     model_form = forms.VMInterfaceForm
     model_form = forms.VMInterfaceForm
 
 
 
 
+@register_model_view(VMInterface, 'edit')
 class VMInterfaceEditView(generic.ObjectEditView):
 class VMInterfaceEditView(generic.ObjectEditView):
     queryset = VMInterface.objects.all()
     queryset = VMInterface.objects.all()
     form = forms.VMInterfaceForm
     form = forms.VMInterfaceForm
 
 
 
 
+@register_model_view(VMInterface, 'delete')
 class VMInterfaceDeleteView(generic.ObjectDeleteView):
 class VMInterfaceDeleteView(generic.ObjectDeleteView):
     queryset = VMInterface.objects.all()
     queryset = VMInterface.objects.all()
 
 

+ 0 - 9
netbox/wireless/urls.py

@@ -12,9 +12,6 @@ urlpatterns = (
     path('wireless-lan-groups/import/', views.WirelessLANGroupBulkImportView.as_view(), name='wirelesslangroup_import'),
     path('wireless-lan-groups/import/', views.WirelessLANGroupBulkImportView.as_view(), name='wirelesslangroup_import'),
     path('wireless-lan-groups/edit/', views.WirelessLANGroupBulkEditView.as_view(), name='wirelesslangroup_bulk_edit'),
     path('wireless-lan-groups/edit/', views.WirelessLANGroupBulkEditView.as_view(), name='wirelesslangroup_bulk_edit'),
     path('wireless-lan-groups/delete/', views.WirelessLANGroupBulkDeleteView.as_view(), name='wirelesslangroup_bulk_delete'),
     path('wireless-lan-groups/delete/', views.WirelessLANGroupBulkDeleteView.as_view(), name='wirelesslangroup_bulk_delete'),
-    path('wireless-lan-groups/<int:pk>/', views.WirelessLANGroupView.as_view(), name='wirelesslangroup'),
-    path('wireless-lan-groups/<int:pk>/edit/', views.WirelessLANGroupEditView.as_view(), name='wirelesslangroup_edit'),
-    path('wireless-lan-groups/<int:pk>/delete/', views.WirelessLANGroupDeleteView.as_view(), name='wirelesslangroup_delete'),
     path('wireless-lan-groups/<int:pk>/', include(get_model_urls('wireless', 'wirelesslangroup'))),
     path('wireless-lan-groups/<int:pk>/', include(get_model_urls('wireless', 'wirelesslangroup'))),
 
 
     # Wireless LANs
     # Wireless LANs
@@ -23,9 +20,6 @@ urlpatterns = (
     path('wireless-lans/import/', views.WirelessLANBulkImportView.as_view(), name='wirelesslan_import'),
     path('wireless-lans/import/', views.WirelessLANBulkImportView.as_view(), name='wirelesslan_import'),
     path('wireless-lans/edit/', views.WirelessLANBulkEditView.as_view(), name='wirelesslan_bulk_edit'),
     path('wireless-lans/edit/', views.WirelessLANBulkEditView.as_view(), name='wirelesslan_bulk_edit'),
     path('wireless-lans/delete/', views.WirelessLANBulkDeleteView.as_view(), name='wirelesslan_bulk_delete'),
     path('wireless-lans/delete/', views.WirelessLANBulkDeleteView.as_view(), name='wirelesslan_bulk_delete'),
-    path('wireless-lans/<int:pk>/', views.WirelessLANView.as_view(), name='wirelesslan'),
-    path('wireless-lans/<int:pk>/edit/', views.WirelessLANEditView.as_view(), name='wirelesslan_edit'),
-    path('wireless-lans/<int:pk>/delete/', views.WirelessLANDeleteView.as_view(), name='wirelesslan_delete'),
     path('wireless-lans/<int:pk>/', include(get_model_urls('wireless', 'wirelesslan'))),
     path('wireless-lans/<int:pk>/', include(get_model_urls('wireless', 'wirelesslan'))),
 
 
     # Wireless links
     # Wireless links
@@ -34,9 +28,6 @@ urlpatterns = (
     path('wireless-links/import/', views.WirelessLinkBulkImportView.as_view(), name='wirelesslink_import'),
     path('wireless-links/import/', views.WirelessLinkBulkImportView.as_view(), name='wirelesslink_import'),
     path('wireless-links/edit/', views.WirelessLinkBulkEditView.as_view(), name='wirelesslink_bulk_edit'),
     path('wireless-links/edit/', views.WirelessLinkBulkEditView.as_view(), name='wirelesslink_bulk_edit'),
     path('wireless-links/delete/', views.WirelessLinkBulkDeleteView.as_view(), name='wirelesslink_bulk_delete'),
     path('wireless-links/delete/', views.WirelessLinkBulkDeleteView.as_view(), name='wirelesslink_bulk_delete'),
-    path('wireless-links/<int:pk>/', views.WirelessLinkView.as_view(), name='wirelesslink'),
-    path('wireless-links/<int:pk>/edit/', views.WirelessLinkEditView.as_view(), name='wirelesslink_edit'),
-    path('wireless-links/<int:pk>/delete/', views.WirelessLinkDeleteView.as_view(), name='wirelesslink_delete'),
     path('wireless-links/<int:pk>/', include(get_model_urls('wireless', 'wirelesslink'))),
     path('wireless-links/<int:pk>/', include(get_model_urls('wireless', 'wirelesslink'))),
 
 
 )
 )

+ 10 - 0
netbox/wireless/views.py

@@ -1,6 +1,7 @@
 from dcim.models import Interface
 from dcim.models import Interface
 from netbox.views import generic
 from netbox.views import generic
 from utilities.utils import count_related
 from utilities.utils import count_related
+from utilities.views import register_model_view
 from . import filtersets, forms, tables
 from . import filtersets, forms, tables
 from .models import *
 from .models import *
 
 
@@ -22,6 +23,7 @@ class WirelessLANGroupListView(generic.ObjectListView):
     table = tables.WirelessLANGroupTable
     table = tables.WirelessLANGroupTable
 
 
 
 
+@register_model_view(WirelessLANGroup)
 class WirelessLANGroupView(generic.ObjectView):
 class WirelessLANGroupView(generic.ObjectView):
     queryset = WirelessLANGroup.objects.all()
     queryset = WirelessLANGroup.objects.all()
 
 
@@ -37,11 +39,13 @@ class WirelessLANGroupView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(WirelessLANGroup, 'edit')
 class WirelessLANGroupEditView(generic.ObjectEditView):
 class WirelessLANGroupEditView(generic.ObjectEditView):
     queryset = WirelessLANGroup.objects.all()
     queryset = WirelessLANGroup.objects.all()
     form = forms.WirelessLANGroupForm
     form = forms.WirelessLANGroupForm
 
 
 
 
+@register_model_view(WirelessLANGroup, 'delete')
 class WirelessLANGroupDeleteView(generic.ObjectDeleteView):
 class WirelessLANGroupDeleteView(generic.ObjectDeleteView):
     queryset = WirelessLANGroup.objects.all()
     queryset = WirelessLANGroup.objects.all()
 
 
@@ -90,6 +94,7 @@ class WirelessLANListView(generic.ObjectListView):
     table = tables.WirelessLANTable
     table = tables.WirelessLANTable
 
 
 
 
+@register_model_view(WirelessLAN)
 class WirelessLANView(generic.ObjectView):
 class WirelessLANView(generic.ObjectView):
     queryset = WirelessLAN.objects.all()
     queryset = WirelessLAN.objects.all()
 
 
@@ -105,11 +110,13 @@ class WirelessLANView(generic.ObjectView):
         }
         }
 
 
 
 
+@register_model_view(WirelessLAN, 'edit')
 class WirelessLANEditView(generic.ObjectEditView):
 class WirelessLANEditView(generic.ObjectEditView):
     queryset = WirelessLAN.objects.all()
     queryset = WirelessLAN.objects.all()
     form = forms.WirelessLANForm
     form = forms.WirelessLANForm
 
 
 
 
+@register_model_view(WirelessLAN, 'delete')
 class WirelessLANDeleteView(generic.ObjectDeleteView):
 class WirelessLANDeleteView(generic.ObjectDeleteView):
     queryset = WirelessLAN.objects.all()
     queryset = WirelessLAN.objects.all()
 
 
@@ -144,15 +151,18 @@ class WirelessLinkListView(generic.ObjectListView):
     table = tables.WirelessLinkTable
     table = tables.WirelessLinkTable
 
 
 
 
+@register_model_view(WirelessLink)
 class WirelessLinkView(generic.ObjectView):
 class WirelessLinkView(generic.ObjectView):
     queryset = WirelessLink.objects.all()
     queryset = WirelessLink.objects.all()
 
 
 
 
+@register_model_view(WirelessLink, 'edit')
 class WirelessLinkEditView(generic.ObjectEditView):
 class WirelessLinkEditView(generic.ObjectEditView):
     queryset = WirelessLink.objects.all()
     queryset = WirelessLink.objects.all()
     form = forms.WirelessLinkForm
     form = forms.WirelessLinkForm
 
 
 
 
+@register_model_view(WirelessLink, 'delete')
 class WirelessLinkDeleteView(generic.ObjectDeleteView):
 class WirelessLinkDeleteView(generic.ObjectDeleteView):
     queryset = WirelessLink.objects.all()
     queryset = WirelessLink.objects.all()
 
 

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác