1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #4997: Introduce OrderedDefaultRouter; move root API views to views.py

This commit is contained in:
Jeremy Stretch
2020-08-13 12:45:38 -04:00
parent a08418bff8
commit fd139a77f5
18 changed files with 118 additions and 97 deletions

View File

@ -14,6 +14,7 @@
* [#4982](https://github.com/netbox-community/netbox/issues/4982) - Extended ObjectVar to allow filtering API query
* [#4994](https://github.com/netbox-community/netbox/issues/4994) - Add `cable` attribute to PowerFeed API serializer
* [#4996](https://github.com/netbox-community/netbox/issues/4996) - Add "connect" buttons to individual device component views
* [#4997](https://github.com/netbox-community/netbox/issues/4997) - The browsable API now lists available endpoints alphabetically
### Bug Fixes

View File

@ -1,18 +1,9 @@
from rest_framework import routers
from utilities.api import OrderedDefaultRouter
from . import views
class CircuitsRootView(routers.APIRootView):
"""
Circuits API root view
"""
def get_view_name(self):
return 'Circuits'
router = routers.DefaultRouter()
router.APIRootView = CircuitsRootView
router = OrderedDefaultRouter()
router.APIRootView = views.CircuitsRootView
# Providers
router.register('providers', views.ProviderViewSet)

View File

@ -2,6 +2,7 @@ from django.db.models import Count, Prefetch
from django.shortcuts import get_object_or_404
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.routers import APIRootView
from circuits import filters
from circuits.models import Provider, CircuitTermination, CircuitType, Circuit
@ -12,6 +13,14 @@ from utilities.api import ModelViewSet
from . import serializers
class CircuitsRootView(APIRootView):
"""
Circuits API root view
"""
def get_view_name(self):
return 'Circuits'
#
# Providers
#

View File

@ -1,18 +1,9 @@
from rest_framework import routers
from utilities.api import OrderedDefaultRouter
from . import views
class DCIMRootView(routers.APIRootView):
"""
DCIM API root view
"""
def get_view_name(self):
return 'DCIM'
router = routers.DefaultRouter()
router.APIRootView = DCIMRootView
router = OrderedDefaultRouter()
router.APIRootView = views.DCIMRootView
# Sites
router.register('regions', views.RegionViewSet)

View File

@ -11,6 +11,7 @@ from drf_yasg.utils import swagger_auto_schema
from rest_framework.decorators import action
from rest_framework.mixins import ListModelMixin
from rest_framework.response import Response
from rest_framework.routers import APIRootView
from rest_framework.viewsets import GenericViewSet, ViewSet
from circuits.models import Circuit
@ -36,6 +37,14 @@ from . import serializers
from .exceptions import MissingFilterException
class DCIMRootView(APIRootView):
"""
DCIM API root view
"""
def get_view_name(self):
return 'DCIM'
# Mixins
class CableTraceMixin(object):

View File

@ -1,18 +1,9 @@
from rest_framework import routers
from utilities.api import OrderedDefaultRouter
from . import views
class ExtrasRootView(routers.APIRootView):
"""
Extras API root view
"""
def get_view_name(self):
return 'Extras'
router = routers.DefaultRouter()
router.APIRootView = ExtrasRootView
router = OrderedDefaultRouter()
router.APIRootView = views.ExtrasRootView
# Custom field choices
router.register('_custom_field_choices', views.CustomFieldChoicesViewSet, basename='custom-field-choice')

View File

@ -8,6 +8,7 @@ from rest_framework import status
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied
from rest_framework.response import Response
from rest_framework.routers import APIRootView
from rest_framework.viewsets import ReadOnlyModelViewSet, ViewSet
from rq import Worker
@ -25,6 +26,14 @@ from utilities.utils import copy_safe_request
from . import serializers
class ExtrasRootView(APIRootView):
"""
Extras API root view
"""
def get_view_name(self):
return 'Extras'
#
# Custom field choices
#

View File

@ -1,18 +1,9 @@
from rest_framework import routers
from utilities.api import OrderedDefaultRouter
from . import views
class IPAMRootView(routers.APIRootView):
"""
IPAM API root view
"""
def get_view_name(self):
return 'IPAM'
router = routers.DefaultRouter()
router.APIRootView = IPAMRootView
router = OrderedDefaultRouter()
router.APIRootView = views.IPAMRootView
# VRFs
router.register('vrfs', views.VRFViewSet)

View File

@ -1,11 +1,12 @@
from django.conf import settings
from django.db.models import Count, Prefetch
from django.db.models import Count
from django.shortcuts import get_object_or_404
from django_pglocks import advisory_lock
from drf_yasg.utils import swagger_auto_schema
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.routers import APIRootView
from extras.api.views import CustomFieldModelViewSet
from ipam import filters
@ -16,6 +17,14 @@ from utilities.utils import get_subquery
from . import serializers
class IPAMRootView(APIRootView):
"""
IPAM API root view
"""
def get_view_name(self):
return 'IPAM'
#
# VRFs
#

View File

@ -1,18 +1,9 @@
from rest_framework import routers
from utilities.api import OrderedDefaultRouter
from . import views
class SecretsRootView(routers.APIRootView):
"""
Secrets API root view
"""
def get_view_name(self):
return 'Secrets'
router = routers.DefaultRouter()
router.APIRootView = SecretsRootView
router = OrderedDefaultRouter()
router.APIRootView = views.SecretsRootView
# Secrets
router.register('secret-roles', views.SecretRoleViewSet)

View File

@ -6,6 +6,7 @@ from django.http import HttpResponseBadRequest
from rest_framework.exceptions import ValidationError
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.routers import APIRootView
from rest_framework.viewsets import ViewSet
from secrets import filters
@ -20,6 +21,14 @@ ERR_PRIVKEY_MISSING = "Private key was not provided."
ERR_PRIVKEY_INVALID = "Invalid private key."
class SecretsRootView(APIRootView):
"""
Secrets API root view
"""
def get_view_name(self):
return 'Secrets'
#
# Secret Roles
#

View File

@ -1,18 +1,9 @@
from rest_framework import routers
from utilities.api import OrderedDefaultRouter
from . import views
class TenancyRootView(routers.APIRootView):
"""
Tenancy API root view
"""
def get_view_name(self):
return 'Tenancy'
router = routers.DefaultRouter()
router.APIRootView = TenancyRootView
router = OrderedDefaultRouter()
router.APIRootView = views.TenancyRootView
# Tenants
router.register('tenant-groups', views.TenantGroupViewSet)

View File

@ -1,3 +1,5 @@
from rest_framework.routers import APIRootView
from circuits.models import Circuit
from dcim.models import Device, Rack, Site
from extras.api.views import CustomFieldModelViewSet
@ -10,6 +12,14 @@ from virtualization.models import VirtualMachine
from . import serializers
class TenancyRootView(APIRootView):
"""
Tenancy API root view
"""
def get_view_name(self):
return 'Tenancy'
#
# Tenant Groups
#

View File

@ -1,18 +1,9 @@
from rest_framework import routers
from utilities.api import OrderedDefaultRouter
from . import views
class UsersRootView(routers.APIRootView):
"""
Users API root view
"""
def get_view_name(self):
return 'Users'
router = routers.DefaultRouter()
router.APIRootView = UsersRootView
router = OrderedDefaultRouter()
router.APIRootView = views.UsersRootView
# Users and groups
router.register('users', views.UserViewSet)

View File

@ -1,5 +1,6 @@
from django.contrib.auth.models import Group, User
from django.db.models import Count
from rest_framework.routers import APIRootView
from users import filters
from users.models import ObjectPermission
@ -8,6 +9,14 @@ from utilities.querysets import RestrictedQuerySet
from . import serializers
class UsersRootView(APIRootView):
"""
Users API root view
"""
def get_view_name(self):
return 'Users'
#
# Users and groups
#

View File

@ -13,6 +13,7 @@ from rest_framework.exceptions import APIException, ValidationError
from rest_framework.permissions import BasePermission
from rest_framework.relations import PrimaryKeyRelatedField, RelatedField
from rest_framework.response import Response
from rest_framework.routers import DefaultRouter
from rest_framework.viewsets import ModelViewSet as _ModelViewSet
from .utils import dict_to_filter_params, dynamic_import
@ -399,3 +400,21 @@ class ModelViewSet(_ModelViewSet):
logger.info(f"Deleting {model._meta.verbose_name} {instance} (PK: {instance.pk})")
return super().perform_destroy(instance)
#
# Routers
#
class OrderedDefaultRouter(DefaultRouter):
def get_api_root_view(self, api_urls=None):
"""
Wrap DRF's DefaultRouter to return an alphabetized list of endpoints.
"""
api_root_dict = OrderedDict()
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)
return self.APIRootView.as_view(api_root_dict=api_root_dict)

View File

@ -1,18 +1,9 @@
from rest_framework import routers
from utilities.api import OrderedDefaultRouter
from . import views
class VirtualizationRootView(routers.APIRootView):
"""
Virtualization API root view
"""
def get_view_name(self):
return 'Virtualization'
router = routers.DefaultRouter()
router.APIRootView = VirtualizationRootView
router = OrderedDefaultRouter()
router.APIRootView = views.VirtualizationRootView
# Clusters
router.register('cluster-types', views.ClusterTypeViewSet)

View File

@ -2,6 +2,7 @@ from django.db.models import Count
from django.shortcuts import get_object_or_404
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.routers import APIRootView
from dcim.models import Device
from extras.api.serializers import RenderedGraphSerializer
@ -14,6 +15,14 @@ from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMac
from . import serializers
class VirtualizationRootView(APIRootView):
"""
Virtualization API root view
"""
def get_view_name(self):
return 'Virtualization'
#
# Clusters
#