diff --git a/rest_framework/routers.py b/rest_framework/routers.py index a04bffc1ac9..01daa7e7d41 100644 --- a/rest_framework/routers.py +++ b/rest_framework/routers.py @@ -26,7 +26,8 @@ from rest_framework.compat import NoReverseMatch from rest_framework.response import Response from rest_framework.reverse import reverse -from rest_framework.schemas import SchemaGenerator, SchemaView +from rest_framework.schemas import SchemaGenerator +from rest_framework.schemas.views import SchemaView from rest_framework.settings import api_settings from rest_framework.urlpatterns import format_suffix_patterns diff --git a/rest_framework/schemas/__init__.py b/rest_framework/schemas/__init__.py index 308f958bb21..2e972ceb6df 100644 --- a/rest_framework/schemas/__init__.py +++ b/rest_framework/schemas/__init__.py @@ -1,19 +1,21 @@ -# The API we expose -# from .views import get_schema_view +from .generators import SchemaGenerator +from .inspectors import AutoSchema, ManualSchema # noqa -# Shared function. TODO: move to utils. -def is_list_view(path, method, view): +def get_schema_view( + title=None, url=None, description=None, urlconf=None, renderer_classes=None, + public=False, patterns=None, generator_class=SchemaGenerator): """ - Return True if the given path/method appears to represent a list view. + Return a schema view. """ - if hasattr(view, 'action'): - # Viewsets have an explicitly defined action, which we can inspect. - return view.action == 'list' - - if method.lower() != 'get': - return False - path_components = path.strip('/').split('/') - if path_components and '{' in path_components[-1]: - return False - return True + # Avoid import cycle on APIView + from .views import SchemaView + generator = generator_class( + title=title, url=url, description=description, + urlconf=urlconf, patterns=patterns, + ) + return SchemaView.as_view( + renderer_classes=renderer_classes, + schema_generator=generator, + public=public, + ) diff --git a/rest_framework/schemas/generators.py b/rest_framework/schemas/generators.py index 544042c9cee..a5778f0f842 100644 --- a/rest_framework/schemas/generators.py +++ b/rest_framework/schemas/generators.py @@ -14,9 +14,8 @@ from rest_framework.request import clone_request from rest_framework.settings import api_settings from rest_framework.utils.model_meta import _get_pk -from rest_framework.views import APIView -from . import is_list_view +from .utils import is_list_view def common_path(paths): @@ -40,6 +39,8 @@ def is_api_view(callback): """ Return `True` if the given view callback is a REST framework view/viewset. """ + # Avoid import cycle on APIView + from rest_framework.views import APIView cls = getattr(callback, 'cls', None) return (cls is not None) and issubclass(cls, APIView) diff --git a/rest_framework/schemas/inspectors.py b/rest_framework/schemas/inspectors.py index 2a15f91e7ca..a99e9453b8c 100644 --- a/rest_framework/schemas/inspectors.py +++ b/rest_framework/schemas/inspectors.py @@ -10,7 +10,7 @@ from rest_framework.settings import api_settings from rest_framework.utils import formatting -from . import is_list_view +from .utils import is_list_view header_regex = re.compile('^[a-zA-Z][0-9A-Za-z_]*:') diff --git a/rest_framework/schemas/utils.py b/rest_framework/schemas/utils.py new file mode 100644 index 00000000000..b82c6585a7e --- /dev/null +++ b/rest_framework/schemas/utils.py @@ -0,0 +1,16 @@ + + +def is_list_view(path, method, view): + """ + Return True if the given path/method appears to represent a list view. + """ + if hasattr(view, 'action'): + # Viewsets have an explicitly defined action, which we can inspect. + return view.action == 'list' + + if method.lower() != 'get': + return False + path_components = path.strip('/').split('/') + if path_components and '{' in path_components[-1]: + return False + return True diff --git a/rest_framework/schemas/views.py b/rest_framework/schemas/views.py index cac4c4ca7eb..d01877872b1 100644 --- a/rest_framework/schemas/views.py +++ b/rest_framework/schemas/views.py @@ -1,6 +1,5 @@ from rest_framework import exceptions, renderers from rest_framework.response import Response -from rest_framework.schemas.generators import SchemaGenerator from rest_framework.settings import api_settings from rest_framework.views import APIView @@ -28,20 +27,3 @@ def get(self, request, *args, **kwargs): 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, patterns=None, generator_class=SchemaGenerator): - """ - Return a schema view. - """ - generator = generator_class( - title=title, url=url, description=description, - urlconf=urlconf, patterns=patterns, - ) - return SchemaView.as_view( - renderer_classes=renderer_classes, - schema_generator=generator, - public=public, - ) diff --git a/rest_framework/views.py b/rest_framework/views.py index 8ec5f14ab26..ccc2047eece 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -19,6 +19,7 @@ from rest_framework.compat import set_rollback from rest_framework.request import Request from rest_framework.response import Response +from rest_framework.schemas import AutoSchema from rest_framework.settings import api_settings from rest_framework.utils import formatting @@ -113,6 +114,7 @@ class APIView(View): # Mark the view as being included or excluded from schema generation. exclude_from_schema = False + schema = AutoSchema() @classmethod def as_view(cls, **initkwargs):