Skip to content

Commit ca0319d

Browse files
committed
initial implementation of OAS 3.0 generateschema
1 parent b14d8ab commit ca0319d

File tree

19 files changed

+2168
-2
lines changed

19 files changed

+2168
-2
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Jason Housley <[email protected]>
1414
Jerel Unruh <[email protected]>
1515
Jonathan Senecal <[email protected]>
1616
Joseba Mendivil <[email protected]>
17+
Kieran Evans <[email protected]>
1718
1819
1920
Matt Layman <https://www.mattlayman.com>

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ any parts of the framework not mentioned in the documentation should generally b
1313
### Added
1414

1515
* Added support for serializing nested serializers as attribute json value introducing setting `JSON_API_SERIALIZE_NESTED_SERIALIZERS_AS_ATTRIBUTE`
16+
* Add support openapi schema and for `generateschema` management command.
1617

1718
### Fixed
1819

docs/usage.md

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
`
22
# Usage
33

44
The DJA package implements a custom renderer, parser, exception handler, query filter backends, and
@@ -32,6 +32,7 @@ REST_FRAMEWORK = {
3232
'rest_framework.renderers.BrowsableAPIRenderer'
3333
),
3434
'DEFAULT_METADATA_CLASS': 'rest_framework_json_api.metadata.JSONAPIMetadata',
35+
'DEFAULT_SCHEMA_CLASS': 'rest_framework_json_api.schemas.openapi.AutoSchema',
3536
'DEFAULT_FILTER_BACKENDS': (
3637
'rest_framework_json_api.filters.QueryParameterValidationFilter',
3738
'rest_framework_json_api.filters.OrderingFilter',
@@ -937,3 +938,117 @@ The `prefetch_related` case will issue 4 queries, but they will be small and fas
937938
### Relationships
938939
### Errors
939940
-->
941+
942+
## Generating an OpenAPI Specification (OAS) 3.0 schema document
943+
944+
DRF 3.10 added a new management command: `generateschema` which can generate an
945+
[OAS 3.0 schema](https://www.openapis.org/) as a YAML or JSON file.
946+
947+
### Settings needed
948+
949+
In order to produce an OAS schema that properly represents the JSON:API structure,
950+
DJA has this same command as an override of DRF's. In order to make sure the DJA
951+
version of the command is used, you must add DJA **ahead of** DRF in the
952+
`INSTALLED_APPS` settings as in this example:
953+
```python
954+
INSTALLED_APPS = [
955+
'django.contrib.contenttypes',
956+
'django.contrib.staticfiles',
957+
'django.contrib.sites',
958+
'django.contrib.sessions',
959+
'django.contrib.auth',
960+
'rest_framework_json_api',
961+
'rest_framework',
962+
'polymorphic',
963+
'example',
964+
'debug_toolbar',
965+
'django_filters',
966+
]
967+
```
968+
969+
You'll also need to make sure you are using the DJA AutoSchema class, either as the default schema class or
970+
explicitly as a view's `schema`:
971+
972+
### Default schema class
973+
974+
```python
975+
REST_FRAMEWORK = {
976+
# ...
977+
'DEFAULT_SCHEMA_CLASS': 'rest_framework_json_api.schemas.openapi.AutoSchema',
978+
}
979+
```
980+
981+
### View-based
982+
983+
You can explicitly use DJA's AutoSchema in your view definition, optionally including an OAS schema document
984+
initializer:
985+
986+
```python
987+
from rest_framework_json_api.schemas.openapi import AutoSchema
988+
989+
openapi_schema = {
990+
'info': {
991+
'version': '1.0',
992+
'title': 'my demo API',
993+
'description': 'A demonstration of [OAS 3.0](https://www.openapis.org) AutoSchema',
994+
'contact': {
995+
'name': 'my name'
996+
},
997+
'license': {
998+
'name': 'BSD 2 clause',
999+
'url': 'https://github.com/django-json-api/django-rest-framework-json-api/blob/master/LICENSE',
1000+
}
1001+
},
1002+
'servers': [
1003+
{'url': 'https://localhost/v1', 'description': 'local docker'},
1004+
{'url': 'http://localhost:8000/v1', 'description': 'local dev'},
1005+
{'url': 'https://api.example.com/v1', 'description': 'demo server'},
1006+
{'url': '{serverURL}', 'description': 'provide your server URL',
1007+
'variables': {'serverURL': {'default': 'http://localhost:8000/v1'}}}
1008+
]
1009+
}
1010+
1011+
1012+
class MyViewSet(ModelViewSet):
1013+
schema = AutoSchema(openapi_schema=openapi_schema)
1014+
```
1015+
1016+
### Get Schema in View
1017+
1018+
Add the following to `urls.py`, to expose the schema at `/openapi`. This can be consumed by (Swagger UI)[https://swagger.io/tools/swagger-ui/] or other tools.
1019+
```python
1020+
from rest_framework.schemas import get_schema_view
1021+
from rest_framework_json_api.schemas.openapi import SchemaGenerator
1022+
1023+
...
1024+
1025+
urlpatterns = [
1026+
path('openapi', get_schema_view(
1027+
title="Example API",
1028+
description="API for all things …",
1029+
version="1.0.0",
1030+
generator_class=SchemaGenerator
1031+
), name='openapi-schema'),
1032+
...
1033+
]
1034+
```
1035+
### Get Schema on Command Line
1036+
To generate an OAS schema document, use something like:
1037+
1038+
```text
1039+
$ django-admin generateschema --settings=example.settings >myschema.yaml
1040+
```
1041+
1042+
You can then use any number of OAS tools such as
1043+
[swagger-ui-watcher](https://www.npmjs.com/package/swagger-ui-watcher)
1044+
to render the schema:
1045+
```text
1046+
$ swagger-ui-watcher myschema.yaml
1047+
```
1048+
1049+
Note: Swagger-ui-watcher will complain that "DELETE operations cannot have a requestBody"
1050+
but it will still work. This
1051+
[error](https://github.com/OAI/OpenAPI-Specification/pull/1937)
1052+
in the OAS specification is expected to be fixed soon.
1053+
([swagger-ui](https://www.npmjs.com/package/swagger-ui) will work silently.)
1054+

example/settings/dev.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
'django.contrib.sites',
2222
'django.contrib.sessions',
2323
'django.contrib.auth',
24+
'rest_framework_json_api',
2425
'rest_framework',
2526
'polymorphic',
2627
'example',
@@ -88,6 +89,7 @@
8889
'rest_framework.renderers.BrowsableAPIRenderer',
8990
),
9091
'DEFAULT_METADATA_CLASS': 'rest_framework_json_api.metadata.JSONAPIMetadata',
92+
'DEFAULT_SCHEMA_CLASS': 'rest_framework_json_api.schemas.openapi.AutoSchema',
9193
'DEFAULT_FILTER_BACKENDS': (
9294
'rest_framework_json_api.filters.OrderingFilter',
9395
'rest_framework_json_api.django_filters.DjangoFilterBackend',

example/templates/swagger-ui.html

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Swagger</title>
5+
<meta charset="utf-8"/>
6+
<meta name="viewport" content="width=device-width, initial-scale=1">
7+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.23.11/swagger-ui.css" integrity="sha256-O3WBPOmqAcumrGlHJtGp6KtuKA4S9sbEu3NCSbacxZ8=" crossorigin="anonymous" />
8+
</head>
9+
<body>
10+
<div id="swagger-ui"></div>
11+
12+
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.23.11/swagger-ui-standalone-preset.js" integrity="sha256-AGfcF/HKnhqGTZNL+pNGJ+yemAzr2tuvbP69pYbn+GU=" crossorigin="anonymous"></script>
13+
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.23.11/swagger-ui-bundle.js" integrity="sha256-wmWvmMbIQjnhA5qXYJAw60JjO3/zvM2T/BMnbdBD26w=" crossorigin="anonymous"></script>
14+
<script>
15+
const ui = SwaggerUIBundle({
16+
url: "{% url schema_url %}",
17+
dom_id: '#swagger-ui',
18+
deepLinking: true,
19+
presets: [
20+
SwaggerUIBundle.presets.apis,
21+
SwaggerUIStandalonePreset
22+
],
23+
plugins: [
24+
SwaggerUIBundle.plugins.DownloadUrl
25+
],
26+
layout: "StandaloneLayout"
27+
})
28+
</script>
29+
</body>
30+
</html>

example/tests/snapshots/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)