Skip to content

Commit

Permalink
Add OpenAPIRenderer by default, and add schema docs. (#6233)
Browse files Browse the repository at this point in the history
* Add OpenAPIRenderer as a default for get_schema_view, and start adding schema docs

* Add optional pyyaml

* Updating schema docs
  • Loading branch information
tomchristie authored Oct 4, 2018
1 parent 18ad329 commit 6522d4a
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 56 deletions.
106 changes: 56 additions & 50 deletions docs/api-guide/schemas.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,50 @@ API schemas are a useful tool that allow for a range of use cases, including
generating reference documentation, or driving dynamic client libraries that
can interact with your API.

## Install Core API
## Install Core API & PyYAML

You'll need to install the `coreapi` package in order to add schema support
for REST framework.
for REST framework. You probably also want to install `pyyaml`, so that you
can render the schema into the commonly used YAML-based OpenAPI format.

pip install coreapi
pip install coreapi pyyaml

## Quickstart

There are two different ways you can serve a schema description for you API.

### Generating a schema with the `generateschema` management command

To generate a static API schema, use the `generateschema` management command.

```shell
$ python manage.py generateschema > schema.yml
```

Once you've generated a schema in this way you can annotate it with any
additional information that cannot be automatically inferred by the schema
generator.

You might want to check your API schema into version control and update it
with each new release, or serve the API schema from your site's static media.

### Adding a view with `get_schema_view`

To add a dynamically generated schema view to your API, use `get_schema_view`.

```python
from rest_framework.schemas import get_schema_view

schema_view = get_schema_view(title="Example API")

urlpatterns = [
url('^schema$', schema_view),
...
]
```

See below [for more details](#the-get_schema_view-shortcut) on customizing a
dynamically generated schema view.

## Internal schema representation

Expand Down Expand Up @@ -71,37 +109,18 @@ endpoint:
In order to be presented in an HTTP response, the internal representation
has to be rendered into the actual bytes that are used in the response.

[Core JSON][corejson] is designed as a canonical format for use with Core API.
REST framework includes a renderer class for handling this media type, which
is available as `renderers.CoreJSONRenderer`.

### Alternate schema formats

Other schema formats such as [Open API][open-api] ("Swagger"),
[JSON HyperSchema][json-hyperschema], or [API Blueprint][api-blueprint] can also
be supported by implementing a custom renderer class that handles converting a
`Document` instance into a bytestring representation.

If there is a Core API codec package that supports encoding into the format you
want to use then implementing the renderer class can be done by using the codec.

#### Example

For example, the `openapi_codec` package provides support for encoding or decoding
to the Open API ("Swagger") format:

from rest_framework import renderers
from openapi_codec import OpenAPICodec

class SwaggerRenderer(renderers.BaseRenderer):
media_type = 'application/openapi+json'
format = 'swagger'
REST framework includes a few different renderers that you can use for
encoding the API schema.

def render(self, data, media_type=None, renderer_context=None):
codec = OpenAPICodec()
return codec.dump(data)
* `renderers.OpenAPIRenderer` - Renders into YAML-based [OpenAPI][openapi], the most widely used API schema format.
* `renderers.JSONOpenAPIRenderer` - Renders into JSON-based [OpenAPI][openapi].
* `renderers.CoreJSONRenderer` - Renders into [Core JSON][corejson], a format designed for
use with the `coreapi` client library.


[Core JSON][corejson] is designed as a canonical format for use with Core API.
REST framework includes a renderer class for handling this media type, which
is available as `renderers.CoreJSONRenderer`.


## Schemas vs Hypermedia
Expand Down Expand Up @@ -325,13 +344,12 @@ ROOT_URLCONF setting.
May be used to pass the set of renderer classes that can be used to render the API root endpoint.

from rest_framework.schemas import get_schema_view
from rest_framework.renderers import CoreJSONRenderer
from my_custom_package import APIBlueprintRenderer
from rest_framework.renderers import JSONOpenAPIRenderer

schema_view = get_schema_view(
title='Server Monitoring API',
url='https://www.example.org/api/',
renderer_classes=[CoreJSONRenderer, APIBlueprintRenderer]
renderer_classes=[JSONOpenAPIRenderer]
)

#### `patterns`
Expand Down Expand Up @@ -364,7 +382,6 @@ Defaults to `settings.DEFAULT_AUTHENTICATION_CLASSES`
May be used to specify the list of permission classes that will apply to the schema endpoint.
Defaults to `settings.DEFAULT_PERMISSION_CLASSES`


## Using an explicit schema view

If you need a little more control than the `get_schema_view()` shortcut gives you,
Expand All @@ -386,7 +403,7 @@ return the schema.
generator = schemas.SchemaGenerator(title='Bookings API')

@api_view()
@renderer_classes([renderers.CoreJSONRenderer])
@renderer_classes([renderers.OpenAPIRenderer])
def schema_view(request):
schema = generator.get_schema(request)
return response.Response(schema)
Expand All @@ -408,7 +425,7 @@ In order to present a schema with endpoints filtered by user permissions,
you need to pass the `request` argument to the `get_schema()` method, like so:

@api_view()
@renderer_classes([renderers.CoreJSONRenderer])
@renderer_classes([renderers.OpenAPIRenderer])
def schema_view(request):
generator = schemas.SchemaGenerator(title='Bookings API')
return response.Response(generator.get_schema(request=request))
Expand All @@ -432,21 +449,10 @@ representation.
)

@api_view()
@renderer_classes([renderers.CoreJSONRenderer])
@renderer_classes([renderers.OpenAPIRenderer])
def schema_view(request):
return response.Response(schema)

## Static schema file

A final option is to write your API schema as a static file, using one
of the available formats, such as Core JSON or Open API.

You could then either:

* Write a schema definition as a static file, and [serve the static file directly][static-files].
* Write a schema definition that is loaded using `Core API`, and then
rendered to one of many available formats, depending on the client request.

---

# Schemas as documentation
Expand Down Expand Up @@ -535,7 +541,7 @@ Arguments:
Returns a `coreapi.Document` instance that represents the API schema.

@api_view
@renderer_classes([renderers.CoreJSONRenderer])
@renderer_classes([renderers.OpenAPIRenderer])
def schema_view(request):
generator = schemas.SchemaGenerator(title='Bookings API')
return Response(generator.get_schema())
Expand Down
1 change: 1 addition & 0 deletions requirements/requirements-optionals.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ django-guardian==1.4.9
django-filter==1.1.0
coreapi==2.3.1
coreschema==0.0.4
pyyaml
11 changes: 5 additions & 6 deletions rest_framework/schemas/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@ class SchemaView(APIView):
def __init__(self, *args, **kwargs):
super(SchemaView, self).__init__(*args, **kwargs)
if self.renderer_classes is None:
self.renderer_classes = [
renderers.OpenAPIRenderer,
renderers.CoreJSONRenderer
]
if renderers.BrowsableAPIRenderer in api_settings.DEFAULT_RENDERER_CLASSES:
self.renderer_classes = [
renderers.CoreJSONRenderer,
renderers.BrowsableAPIRenderer,
]
else:
self.renderer_classes = [renderers.CoreJSONRenderer]
self.renderer_classes += [renderers.BrowsableAPIRenderer]

def get(self, request, *args, **kwargs):
schema = self.schema_generator.get_schema(request, self.public)
Expand Down

0 comments on commit 6522d4a

Please sign in to comment.