diff --git a/docs/plugins/development/rest-api.md b/docs/plugins/development/rest-api.md index 4f275dc9e..a7265dee9 100644 --- a/docs/plugins/development/rest-api.md +++ b/docs/plugins/development/rest-api.md @@ -70,10 +70,10 @@ Routers should be exposed in `api/urls.py`. This file **must** define a variable ```python # api/urls.py -from rest_framework import routers +from netbox.api.routers import NetBoxRouter from .views import MyModelViewSet -router = routers.DefaultRouter() +router = NetBoxRouter() router.register('my-model', MyModelViewSet) urlpatterns = router.urls ``` diff --git a/netbox/circuits/api/urls.py b/netbox/circuits/api/urls.py index 5389e0bde..616adfaa4 100644 --- a/netbox/circuits/api/urls.py +++ b/netbox/circuits/api/urls.py @@ -1,8 +1,8 @@ -from netbox.api import OrderedDefaultRouter +from netbox.api import NetBoxRouter from . import views -router = OrderedDefaultRouter() +router = NetBoxRouter() router.APIRootView = views.CircuitsRootView # Providers diff --git a/netbox/dcim/api/urls.py b/netbox/dcim/api/urls.py index c6f48aed3..f67d241d5 100644 --- a/netbox/dcim/api/urls.py +++ b/netbox/dcim/api/urls.py @@ -1,8 +1,8 @@ -from netbox.api import OrderedDefaultRouter +from netbox.api import NetBoxRouter from . import views -router = OrderedDefaultRouter() +router = NetBoxRouter() router.APIRootView = views.DCIMRootView # Sites diff --git a/netbox/extras/api/urls.py b/netbox/extras/api/urls.py index 565f2cdc7..dd6a5aeff 100644 --- a/netbox/extras/api/urls.py +++ b/netbox/extras/api/urls.py @@ -1,8 +1,8 @@ -from netbox.api import OrderedDefaultRouter +from netbox.api import NetBoxRouter from . import views -router = OrderedDefaultRouter() +router = NetBoxRouter() router.APIRootView = views.ExtrasRootView # Webhooks diff --git a/netbox/ipam/api/urls.py b/netbox/ipam/api/urls.py index 8a68db9be..99e039eff 100644 --- a/netbox/ipam/api/urls.py +++ b/netbox/ipam/api/urls.py @@ -1,11 +1,11 @@ from django.urls import path -from netbox.api import OrderedDefaultRouter +from netbox.api import NetBoxRouter from ipam.models import IPRange, Prefix from . import views -router = OrderedDefaultRouter() +router = NetBoxRouter() router.APIRootView = views.IPAMRootView # ASNs diff --git a/netbox/netbox/api/__init__.py b/netbox/netbox/api/__init__.py index 334ee09f7..1eaa7d1c4 100644 --- a/netbox/netbox/api/__init__.py +++ b/netbox/netbox/api/__init__.py @@ -1,5 +1,5 @@ from .fields import ChoiceField, ContentTypeField, SerializedPKRelatedField -from .routers import OrderedDefaultRouter +from .routers import NetBoxRouter from .serializers import BulkOperationSerializer, ValidatedModelSerializer, WritableNestedSerializer @@ -7,7 +7,7 @@ __all__ = ( 'BulkOperationSerializer', 'ChoiceField', 'ContentTypeField', - 'OrderedDefaultRouter', + 'NetBoxRouter', 'SerializedPKRelatedField', 'ValidatedModelSerializer', 'WritableNestedSerializer', diff --git a/netbox/netbox/api/routers.py b/netbox/netbox/api/routers.py index 71df1796e..a285e4d42 100644 --- a/netbox/netbox/api/routers.py +++ b/netbox/netbox/api/routers.py @@ -1,14 +1,16 @@ -from collections import OrderedDict - from rest_framework.routers import DefaultRouter -class OrderedDefaultRouter(DefaultRouter): - +class NetBoxRouter(DefaultRouter): + """ + Extend DRF's built-in DefaultRouter to: + 1. Support bulk operations + 2. Alphabetically order endpoints under the root view + """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - # Extend the list view mappings to support the DELETE operation + # Update the list view mappings to support bulk operations self.routes[0].mapping.update({ 'put': 'bulk_update', 'patch': 'bulk_partial_update', @@ -19,7 +21,7 @@ class OrderedDefaultRouter(DefaultRouter): """ Wrap DRF's DefaultRouter to return an alphabetized list of endpoints. """ - api_root_dict = OrderedDict() + api_root_dict = {} list_name = self.routes[0].name for prefix, viewset, basename in sorted(self.registry, key=lambda x: x[0]): api_root_dict[prefix] = list_name.format(basename=basename) diff --git a/netbox/tenancy/api/urls.py b/netbox/tenancy/api/urls.py index 00e1a6469..7dbe59ea4 100644 --- a/netbox/tenancy/api/urls.py +++ b/netbox/tenancy/api/urls.py @@ -1,8 +1,8 @@ -from netbox.api import OrderedDefaultRouter +from netbox.api import NetBoxRouter from . import views -router = OrderedDefaultRouter() +router = NetBoxRouter() router.APIRootView = views.TenancyRootView # Tenants diff --git a/netbox/users/api/urls.py b/netbox/users/api/urls.py index 15e4d1530..f46cc1680 100644 --- a/netbox/users/api/urls.py +++ b/netbox/users/api/urls.py @@ -1,10 +1,10 @@ from django.urls import include, path -from netbox.api import OrderedDefaultRouter +from netbox.api import NetBoxRouter from . import views -router = OrderedDefaultRouter() +router = NetBoxRouter() router.APIRootView = views.UsersRootView # Users and groups diff --git a/netbox/virtualization/api/urls.py b/netbox/virtualization/api/urls.py index d9df2fcfe..07b20bfd7 100644 --- a/netbox/virtualization/api/urls.py +++ b/netbox/virtualization/api/urls.py @@ -1,8 +1,8 @@ -from netbox.api import OrderedDefaultRouter +from netbox.api import NetBoxRouter from . import views -router = OrderedDefaultRouter() +router = NetBoxRouter() router.APIRootView = views.VirtualizationRootView # Clusters diff --git a/netbox/wireless/api/urls.py b/netbox/wireless/api/urls.py index b02aa67c0..47799bd3a 100644 --- a/netbox/wireless/api/urls.py +++ b/netbox/wireless/api/urls.py @@ -1,8 +1,8 @@ -from netbox.api import OrderedDefaultRouter +from netbox.api import NetBoxRouter from . import views -router = OrderedDefaultRouter() +router = NetBoxRouter() router.APIRootView = views.WirelessRootView router.register('wireless-lan-groups', views.WirelessLANGroupViewSet)