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 * [#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 * [#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 * [#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 ### Bug Fixes

View File

@ -1,18 +1,9 @@
from rest_framework import routers from utilities.api import OrderedDefaultRouter
from . import views from . import views
class CircuitsRootView(routers.APIRootView): router = OrderedDefaultRouter()
""" router.APIRootView = views.CircuitsRootView
Circuits API root view
"""
def get_view_name(self):
return 'Circuits'
router = routers.DefaultRouter()
router.APIRootView = CircuitsRootView
# Providers # Providers
router.register('providers', views.ProviderViewSet) 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 django.shortcuts import get_object_or_404
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.routers import APIRootView
from circuits import filters from circuits import filters
from circuits.models import Provider, CircuitTermination, CircuitType, Circuit from circuits.models import Provider, CircuitTermination, CircuitType, Circuit
@ -12,6 +13,14 @@ from utilities.api import ModelViewSet
from . import serializers from . import serializers
class CircuitsRootView(APIRootView):
"""
Circuits API root view
"""
def get_view_name(self):
return 'Circuits'
# #
# Providers # Providers
# #

View File

@ -1,18 +1,9 @@
from rest_framework import routers from utilities.api import OrderedDefaultRouter
from . import views from . import views
class DCIMRootView(routers.APIRootView): router = OrderedDefaultRouter()
""" router.APIRootView = views.DCIMRootView
DCIM API root view
"""
def get_view_name(self):
return 'DCIM'
router = routers.DefaultRouter()
router.APIRootView = DCIMRootView
# Sites # Sites
router.register('regions', views.RegionViewSet) 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.decorators import action
from rest_framework.mixins import ListModelMixin from rest_framework.mixins import ListModelMixin
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.routers import APIRootView
from rest_framework.viewsets import GenericViewSet, ViewSet from rest_framework.viewsets import GenericViewSet, ViewSet
from circuits.models import Circuit from circuits.models import Circuit
@ -36,6 +37,14 @@ from . import serializers
from .exceptions import MissingFilterException from .exceptions import MissingFilterException
class DCIMRootView(APIRootView):
"""
DCIM API root view
"""
def get_view_name(self):
return 'DCIM'
# Mixins # Mixins
class CableTraceMixin(object): class CableTraceMixin(object):

View File

@ -1,18 +1,9 @@
from rest_framework import routers from utilities.api import OrderedDefaultRouter
from . import views from . import views
class ExtrasRootView(routers.APIRootView): router = OrderedDefaultRouter()
""" router.APIRootView = views.ExtrasRootView
Extras API root view
"""
def get_view_name(self):
return 'Extras'
router = routers.DefaultRouter()
router.APIRootView = ExtrasRootView
# Custom field choices # Custom field choices
router.register('_custom_field_choices', views.CustomFieldChoicesViewSet, basename='custom-field-choice') 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.decorators import action
from rest_framework.exceptions import PermissionDenied from rest_framework.exceptions import PermissionDenied
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.routers import APIRootView
from rest_framework.viewsets import ReadOnlyModelViewSet, ViewSet from rest_framework.viewsets import ReadOnlyModelViewSet, ViewSet
from rq import Worker from rq import Worker
@ -25,6 +26,14 @@ from utilities.utils import copy_safe_request
from . import serializers from . import serializers
class ExtrasRootView(APIRootView):
"""
Extras API root view
"""
def get_view_name(self):
return 'Extras'
# #
# Custom field choices # Custom field choices
# #

View File

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

View File

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

View File

@ -1,18 +1,9 @@
from rest_framework import routers from utilities.api import OrderedDefaultRouter
from . import views from . import views
class SecretsRootView(routers.APIRootView): router = OrderedDefaultRouter()
""" router.APIRootView = views.SecretsRootView
Secrets API root view
"""
def get_view_name(self):
return 'Secrets'
router = routers.DefaultRouter()
router.APIRootView = SecretsRootView
# Secrets # Secrets
router.register('secret-roles', views.SecretRoleViewSet) 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.exceptions import ValidationError
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.routers import APIRootView
from rest_framework.viewsets import ViewSet from rest_framework.viewsets import ViewSet
from secrets import filters from secrets import filters
@ -20,6 +21,14 @@ ERR_PRIVKEY_MISSING = "Private key was not provided."
ERR_PRIVKEY_INVALID = "Invalid private key." ERR_PRIVKEY_INVALID = "Invalid private key."
class SecretsRootView(APIRootView):
"""
Secrets API root view
"""
def get_view_name(self):
return 'Secrets'
# #
# Secret Roles # Secret Roles
# #

View File

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

View File

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

View File

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

View File

@ -1,5 +1,6 @@
from django.contrib.auth.models import Group, User from django.contrib.auth.models import Group, User
from django.db.models import Count from django.db.models import Count
from rest_framework.routers import APIRootView
from users import filters from users import filters
from users.models import ObjectPermission from users.models import ObjectPermission
@ -8,6 +9,14 @@ from utilities.querysets import RestrictedQuerySet
from . import serializers from . import serializers
class UsersRootView(APIRootView):
"""
Users API root view
"""
def get_view_name(self):
return 'Users'
# #
# Users and groups # 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.permissions import BasePermission
from rest_framework.relations import PrimaryKeyRelatedField, RelatedField from rest_framework.relations import PrimaryKeyRelatedField, RelatedField
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.routers import DefaultRouter
from rest_framework.viewsets import ModelViewSet as _ModelViewSet from rest_framework.viewsets import ModelViewSet as _ModelViewSet
from .utils import dict_to_filter_params, dynamic_import 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})") logger.info(f"Deleting {model._meta.verbose_name} {instance} (PK: {instance.pk})")
return super().perform_destroy(instance) 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 from . import views
class VirtualizationRootView(routers.APIRootView): router = OrderedDefaultRouter()
""" router.APIRootView = views.VirtualizationRootView
Virtualization API root view
"""
def get_view_name(self):
return 'Virtualization'
router = routers.DefaultRouter()
router.APIRootView = VirtualizationRootView
# Clusters # Clusters
router.register('cluster-types', views.ClusterTypeViewSet) 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 django.shortcuts import get_object_or_404
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.routers import APIRootView
from dcim.models import Device from dcim.models import Device
from extras.api.serializers import RenderedGraphSerializer from extras.api.serializers import RenderedGraphSerializer
@ -14,6 +15,14 @@ from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMac
from . import serializers from . import serializers
class VirtualizationRootView(APIRootView):
"""
Virtualization API root view
"""
def get_view_name(self):
return 'Virtualization'
# #
# Clusters # Clusters
# #