Added url and schema_url arguments (#4321)

This commit is contained in:
Tom Christie 2016-07-28 12:08:34 +01:00 committed by GitHub
parent 6a7d34ec34
commit 061e0ed084
4 changed files with 39 additions and 11 deletions

View File

@ -128,9 +128,11 @@ that include the Core JSON media type in their `Accept` header.
This is a great zero-configuration option for when you want to get up and This is a great zero-configuration option for when you want to get up and
running really quickly. running really quickly.
The only other available option to `DefaultRouter` is `schema_renderers`, which The other available options to `DefaultRouter` are:
may be used to pass the set of renderer classes that can be used to render
schema output. #### schema_renderers
May be used to pass the set of renderer classes that can be used to render schema output.
from rest_framework.renderers import CoreJSONRenderer from rest_framework.renderers import CoreJSONRenderer
from my_custom_package import APIBlueprintRenderer from my_custom_package import APIBlueprintRenderer
@ -139,6 +141,17 @@ schema output.
CoreJSONRenderer, APIBlueprintRenderer CoreJSONRenderer, APIBlueprintRenderer
]) ])
#### schema_url
May be used to pass the root URL for the schema. This can either be used to ensure that
the schema URLs include a canonical hostname and schema, or to ensure that all the
schema URLs include a path prefix.
router = DefaultRouter(
schema_title='Server Monitoring API',
schema_url='https://www.example.org/api/'
)
If you want more flexibility over the schema output then you'll need to consider If you want more flexibility over the schema output then you'll need to consider
using `SchemaGenerator` instead. using `SchemaGenerator` instead.
@ -264,6 +277,7 @@ Typically you'll instantiate `SchemaGenerator` with a single argument, like so:
Arguments: Arguments:
* `title` - The name of the API. **required** * `title` - The name of the API. **required**
* `url` - The root URL of the API schema. This option is not required unless the schema is included under path prefix.
* `patterns` - A list of URLs to inspect when generating the schema. Defaults to the project's URL conf. * `patterns` - A list of URLs to inspect when generating the schema. Defaults to the project's URL conf.
* `urlconf` - A URL conf module name to use when generating the schema. Defaults to `settings.ROOT_URLCONF`. * `urlconf` - A URL conf module name to use when generating the schema. Defaults to `settings.ROOT_URLCONF`.

View File

@ -23,6 +23,12 @@ except ImportError:
from django.utils import importlib # Will be removed in Django 1.9 from django.utils import importlib # Will be removed in Django 1.9
try:
import urlparse # Python 2.x
except ImportError:
import urllib.parse as urlparse
def unicode_repr(instance): def unicode_repr(instance):
# Get the repr of an instance, but ensure it is a unicode string # Get the repr of an instance, but ensure it is a unicode string
# on both python 3 (already the case) and 2 (not the case). # on both python 3 (already the case) and 2 (not the case).

View File

@ -278,11 +278,14 @@ class DefaultRouter(SimpleRouter):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
if 'schema_renderers' in kwargs: if 'schema_renderers' in kwargs:
assert 'schema_title' in kwargs, 'Missing "schema_title" argument.' 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_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) self.schema_renderers = kwargs.pop('schema_renderers', self.default_schema_renderers)
super(DefaultRouter, self).__init__(*args, **kwargs) super(DefaultRouter, self).__init__(*args, **kwargs)
def get_api_root_view(self, schema_urls=None): def get_api_root_view(self, api_urls=None):
""" """
Return a view to use as the API root. Return a view to use as the API root.
""" """
@ -294,11 +297,12 @@ class DefaultRouter(SimpleRouter):
view_renderers = list(api_settings.DEFAULT_RENDERER_CLASSES) view_renderers = list(api_settings.DEFAULT_RENDERER_CLASSES)
schema_media_types = [] schema_media_types = []
if schema_urls and self.schema_title: if api_urls and self.schema_title:
view_renderers += list(self.schema_renderers) view_renderers += list(self.schema_renderers)
schema_generator = SchemaGenerator( schema_generator = SchemaGenerator(
title=self.schema_title, title=self.schema_title,
patterns=schema_urls url=self.schema_url,
patterns=api_urls
) )
schema_media_types = [ schema_media_types = [
renderer.media_type renderer.media_type
@ -347,7 +351,7 @@ class DefaultRouter(SimpleRouter):
urls = super(DefaultRouter, self).get_urls() urls = super(DefaultRouter, self).get_urls()
if self.include_root_view: if self.include_root_view:
view = self.get_api_root_view(schema_urls=urls) view = self.get_api_root_view(api_urls=urls)
root_url = url(r'^$', view, name=self.root_view_name) root_url = url(r'^$', view, name=self.root_view_name)
urls.append(root_url) urls.append(root_url)

View File

@ -6,7 +6,7 @@ from django.core.urlresolvers import RegexURLPattern, RegexURLResolver
from django.utils import six from django.utils import six
from rest_framework import exceptions, serializers from rest_framework import exceptions, serializers
from rest_framework.compat import coreapi, uritemplate from rest_framework.compat import coreapi, uritemplate, urlparse
from rest_framework.request import clone_request from rest_framework.request import clone_request
from rest_framework.views import APIView from rest_framework.views import APIView
@ -57,7 +57,7 @@ class SchemaGenerator(object):
'delete': 'destroy', 'delete': 'destroy',
} }
def __init__(self, title=None, patterns=None, urlconf=None): def __init__(self, title=None, url=None, patterns=None, urlconf=None):
assert coreapi, '`coreapi` must be installed for schema support.' assert coreapi, '`coreapi` must be installed for schema support.'
if patterns is None and urlconf is not None: if patterns is None and urlconf is not None:
@ -70,7 +70,11 @@ class SchemaGenerator(object):
urls = import_module(settings.ROOT_URLCONF) urls = import_module(settings.ROOT_URLCONF)
patterns = urls.urlpatterns patterns = urls.urlpatterns
if url and not url.endswith('/'):
url += '/'
self.title = title self.title = title
self.url = url
self.endpoints = self.get_api_endpoints(patterns) self.endpoints = self.get_api_endpoints(patterns)
def get_schema(self, request=None): def get_schema(self, request=None):
@ -102,7 +106,7 @@ class SchemaGenerator(object):
insert_into(content, key, link) insert_into(content, key, link)
# Return the schema document. # Return the schema document.
return coreapi.Document(title=self.title, content=content) return coreapi.Document(title=self.title, content=content, url=self.url)
def get_api_endpoints(self, patterns, prefix=''): def get_api_endpoints(self, patterns, prefix=''):
""" """
@ -203,7 +207,7 @@ class SchemaGenerator(object):
encoding = None encoding = None
return coreapi.Link( return coreapi.Link(
url=path, url=urlparse.urljoin(self.url, path),
action=method.lower(), action=method.lower(),
encoding=encoding, encoding=encoding,
fields=fields fields=fields