mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-03 13:14:30 +03:00
Extract APISchemaView and APIRootView out of the DefaultRouter. (#4707)
This commit is contained in:
parent
cf5d401a0e
commit
537df7a6ad
|
@ -22,12 +22,11 @@ from collections import OrderedDict, namedtuple
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
from rest_framework import exceptions, renderers, views
|
from rest_framework import views
|
||||||
from rest_framework.compat import NoReverseMatch
|
from rest_framework.compat import NoReverseMatch
|
||||||
from rest_framework.renderers import BrowsableAPIRenderer
|
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.reverse import reverse
|
from rest_framework.reverse import reverse
|
||||||
from rest_framework.schemas import SchemaGenerator
|
from rest_framework.schemas import SchemaGenerator, SchemaView
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
from rest_framework.urlpatterns import format_suffix_patterns
|
from rest_framework.urlpatterns import format_suffix_patterns
|
||||||
|
|
||||||
|
@ -276,78 +275,19 @@ class SimpleRouter(BaseRouter):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class DefaultRouter(SimpleRouter):
|
class APIRootView(views.APIView):
|
||||||
"""
|
"""
|
||||||
The default router extends the SimpleRouter, but also adds in a default
|
The default basic root view for DefaultRouter
|
||||||
API root view, and adds format suffix patterns to the URLs.
|
|
||||||
"""
|
"""
|
||||||
include_root_view = True
|
|
||||||
include_format_suffixes = True
|
|
||||||
root_view_name = 'api-root'
|
|
||||||
default_schema_renderers = [renderers.CoreJSONRenderer, BrowsableAPIRenderer]
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
if 'schema_title' in kwargs:
|
|
||||||
warnings.warn(
|
|
||||||
"Including a schema directly via a router is now pending "
|
|
||||||
"deprecation. Use `get_schema_view()` instead.",
|
|
||||||
PendingDeprecationWarning
|
|
||||||
)
|
|
||||||
if 'schema_renderers' in kwargs:
|
|
||||||
assert 'schema_title' in kwargs, 'Missing "schema_title" argument.'
|
|
||||||
if 'schema_url' in kwargs:
|
|
||||||
assert 'schema_title' in kwargs, 'Missing "schema_title" argument.'
|
|
||||||
self.schema_title = kwargs.pop('schema_title', None)
|
|
||||||
self.schema_url = kwargs.pop('schema_url', None)
|
|
||||||
self.schema_renderers = kwargs.pop('schema_renderers', self.default_schema_renderers)
|
|
||||||
if 'root_renderers' in kwargs:
|
|
||||||
self.root_renderers = kwargs.pop('root_renderers')
|
|
||||||
else:
|
|
||||||
self.root_renderers = list(api_settings.DEFAULT_RENDERER_CLASSES)
|
|
||||||
super(DefaultRouter, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
def get_schema_root_view(self, api_urls=None):
|
|
||||||
"""
|
|
||||||
Return a schema root view.
|
|
||||||
"""
|
|
||||||
schema_renderers = self.schema_renderers
|
|
||||||
schema_generator = SchemaGenerator(
|
|
||||||
title=self.schema_title,
|
|
||||||
url=self.schema_url,
|
|
||||||
patterns=api_urls
|
|
||||||
)
|
|
||||||
|
|
||||||
class APISchemaView(views.APIView):
|
|
||||||
_ignore_model_permissions = True
|
|
||||||
exclude_from_schema = True
|
|
||||||
renderer_classes = schema_renderers
|
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
|
||||||
schema = schema_generator.get_schema(request)
|
|
||||||
if schema is None:
|
|
||||||
raise exceptions.PermissionDenied()
|
|
||||||
return Response(schema)
|
|
||||||
|
|
||||||
return APISchemaView.as_view()
|
|
||||||
|
|
||||||
def get_api_root_view(self, api_urls=None):
|
|
||||||
"""
|
|
||||||
Return a basic root view.
|
|
||||||
"""
|
|
||||||
api_root_dict = OrderedDict()
|
|
||||||
list_name = self.routes[0].name
|
|
||||||
for prefix, viewset, basename in self.registry:
|
|
||||||
api_root_dict[prefix] = list_name.format(basename=basename)
|
|
||||||
|
|
||||||
class APIRootView(views.APIView):
|
|
||||||
_ignore_model_permissions = True
|
_ignore_model_permissions = True
|
||||||
exclude_from_schema = True
|
exclude_from_schema = True
|
||||||
|
api_root_dict = None
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
# Return a plain {"name": "hyperlink"} response.
|
# Return a plain {"name": "hyperlink"} response.
|
||||||
ret = OrderedDict()
|
ret = OrderedDict()
|
||||||
namespace = request.resolver_match.namespace
|
namespace = request.resolver_match.namespace
|
||||||
for key, url_name in api_root_dict.items():
|
for key, url_name in self.api_root_dict.items():
|
||||||
if namespace:
|
if namespace:
|
||||||
url_name = namespace + ':' + url_name
|
url_name = namespace + ':' + url_name
|
||||||
try:
|
try:
|
||||||
|
@ -364,7 +304,72 @@ class DefaultRouter(SimpleRouter):
|
||||||
|
|
||||||
return Response(ret)
|
return Response(ret)
|
||||||
|
|
||||||
return APIRootView.as_view()
|
|
||||||
|
class DefaultRouter(SimpleRouter):
|
||||||
|
"""
|
||||||
|
The default router extends the SimpleRouter, but also adds in a default
|
||||||
|
API root view, and adds format suffix patterns to the URLs.
|
||||||
|
"""
|
||||||
|
include_root_view = True
|
||||||
|
include_format_suffixes = True
|
||||||
|
root_view_name = 'api-root'
|
||||||
|
default_schema_renderers = None
|
||||||
|
APIRootView = APIRootView
|
||||||
|
APISchemaView = SchemaView
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
if 'schema_title' in kwargs:
|
||||||
|
warnings.warn(
|
||||||
|
"Including a schema directly via a router is now pending "
|
||||||
|
"deprecation. Use `get_schema_view()` instead.",
|
||||||
|
PendingDeprecationWarning
|
||||||
|
)
|
||||||
|
if 'schema_renderers' in kwargs:
|
||||||
|
assert 'schema_title' in kwargs, 'Missing "schema_title" argument.'
|
||||||
|
if 'schema_url' in kwargs:
|
||||||
|
assert 'schema_title' in kwargs, 'Missing "schema_title" argument.'
|
||||||
|
self.schema_title = kwargs.pop('schema_title', None)
|
||||||
|
self.schema_url = kwargs.pop('schema_url', None)
|
||||||
|
self.schema_renderers = kwargs.pop('schema_renderers', self.default_schema_renderers)
|
||||||
|
if self.default_schema_renderers:
|
||||||
|
warnings.warn(
|
||||||
|
"The 'DefaultRouter.default_schema_renderers' is pending "
|
||||||
|
"deprecation. You should override "
|
||||||
|
"'DefaultRouter.APISchemaView' instead.",
|
||||||
|
PendingDeprecationWarning
|
||||||
|
)
|
||||||
|
|
||||||
|
if 'root_renderers' in kwargs:
|
||||||
|
self.root_renderers = kwargs.pop('root_renderers')
|
||||||
|
else:
|
||||||
|
self.root_renderers = list(api_settings.DEFAULT_RENDERER_CLASSES)
|
||||||
|
super(DefaultRouter, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_schema_root_view(self, api_urls=None):
|
||||||
|
"""
|
||||||
|
Return a schema root view.
|
||||||
|
"""
|
||||||
|
schema_generator = SchemaGenerator(
|
||||||
|
title=self.schema_title,
|
||||||
|
url=self.schema_url,
|
||||||
|
patterns=api_urls
|
||||||
|
)
|
||||||
|
|
||||||
|
return self.APISchemaView.as_view(
|
||||||
|
renderer_classes=self.schema_renderers,
|
||||||
|
schema_generator=schema_generator,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_api_root_view(self, api_urls=None):
|
||||||
|
"""
|
||||||
|
Return a basic root view.
|
||||||
|
"""
|
||||||
|
api_root_dict = OrderedDict()
|
||||||
|
list_name = self.routes[0].name
|
||||||
|
for prefix, viewset, basename in self.registry:
|
||||||
|
api_root_dict[prefix] = list_name.format(basename=basename)
|
||||||
|
|
||||||
|
return self.APIRootView.as_view(api_root_dict=api_root_dict)
|
||||||
|
|
||||||
def get_urls(self):
|
def get_urls(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -665,28 +665,38 @@ class SchemaGenerator(object):
|
||||||
return named_path_components + [action]
|
return named_path_components + [action]
|
||||||
|
|
||||||
|
|
||||||
|
class SchemaView(APIView):
|
||||||
|
_ignore_model_permissions = True
|
||||||
|
exclude_from_schema = True
|
||||||
|
renderer_classes = None
|
||||||
|
schema_generator = None
|
||||||
|
public = False
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(SchemaView, self).__init__(*args, **kwargs)
|
||||||
|
if self.renderer_classes is None:
|
||||||
|
if renderers.BrowsableAPIRenderer in api_settings.DEFAULT_RENDERER_CLASSES:
|
||||||
|
self.renderer_classes = [
|
||||||
|
renderers.CoreJSONRenderer,
|
||||||
|
renderers.BrowsableAPIRenderer,
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
self.renderer_classes = [renderers.CoreJSONRenderer]
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
schema = self.schema_generator.get_schema(request, self.public)
|
||||||
|
if schema is None:
|
||||||
|
raise exceptions.PermissionDenied()
|
||||||
|
return Response(schema)
|
||||||
|
|
||||||
|
|
||||||
def get_schema_view(title=None, url=None, description=None, urlconf=None, renderer_classes=None, public=False):
|
def get_schema_view(title=None, url=None, description=None, urlconf=None, renderer_classes=None, public=False):
|
||||||
"""
|
"""
|
||||||
Return a schema view.
|
Return a schema view.
|
||||||
"""
|
"""
|
||||||
generator = SchemaGenerator(title=title, url=url, description=description, urlconf=urlconf)
|
generator = SchemaGenerator(title=title, url=url, description=description, urlconf=urlconf)
|
||||||
if renderer_classes is None:
|
return SchemaView.as_view(
|
||||||
if renderers.BrowsableAPIRenderer in api_settings.DEFAULT_RENDERER_CLASSES:
|
renderer_classes=renderer_classes,
|
||||||
rclasses = [renderers.CoreJSONRenderer, renderers.BrowsableAPIRenderer]
|
schema_generator=generator,
|
||||||
else:
|
public=public,
|
||||||
rclasses = [renderers.CoreJSONRenderer]
|
)
|
||||||
else:
|
|
||||||
rclasses = renderer_classes
|
|
||||||
|
|
||||||
class SchemaView(APIView):
|
|
||||||
_ignore_model_permissions = True
|
|
||||||
exclude_from_schema = True
|
|
||||||
renderer_classes = rclasses
|
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
|
||||||
schema = generator.get_schema(request, public)
|
|
||||||
if schema is None:
|
|
||||||
raise exceptions.PermissionDenied()
|
|
||||||
return Response(schema)
|
|
||||||
|
|
||||||
return SchemaView.as_view()
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user