Skip to content

Commit 07034ae

Browse files
committed
initial implementation of OAS 3.0 generateschema
1 parent 959aec7 commit 07034ae

File tree

17 files changed

+2207
-3
lines changed

17 files changed

+2207
-3
lines changed

AUTHORS

+1
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

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ 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 optional support for [openapi](https://www.openapis.org/) schema generation. Enable with:
17+
```
18+
pip install djangorestframework-jsonapi['openapi']
19+
```
20+
1621

1722
### Fixed
1823

README.rst

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ From PyPI
106106
$ # for optional package integrations
107107
$ pip install djangorestframework-jsonapi['django-filter']
108108
$ pip install djangorestframework-jsonapi['django-polymorphic']
109+
$ pip install djangorestframework-jsonapi['openapi']
109110

110111

111112
From Source

docs/getting-started.md

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ From PyPI
6565
# for optional package integrations
6666
pip install djangorestframework-jsonapi['django-filter']
6767
pip install djangorestframework-jsonapi['django-polymorphic']
68+
pip install djangorestframework-jsonapi['openapi']
6869

6970
From Source
7071

docs/usage.md

+116-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
# Usage
32

43
The DJA package implements a custom renderer, parser, exception handler, query filter backends, and
@@ -32,6 +31,7 @@ REST_FRAMEWORK = {
3231
'rest_framework.renderers.BrowsableAPIRenderer'
3332
),
3433
'DEFAULT_METADATA_CLASS': 'rest_framework_json_api.metadata.JSONAPIMetadata',
34+
'DEFAULT_SCHEMA_CLASS': 'rest_framework_json_api.schemas.openapi.AutoSchema',
3535
'DEFAULT_FILTER_BACKENDS': (
3636
'rest_framework_json_api.filters.QueryParameterValidationFilter',
3737
'rest_framework_json_api.filters.OrderingFilter',
@@ -944,3 +944,118 @@ The `prefetch_related` case will issue 4 queries, but they will be small and fas
944944
### Relationships
945945
### Errors
946946
-->
947+
948+
## Generating an OpenAPI Specification (OAS) 3.0 schema document
949+
950+
DRF >= 3.12 has a [new OAS schema functionality](https://www.django-rest-framework.org/api-guide/schemas/) to generate an
951+
[OAS 3.0 schema](https://www.openapis.org/) as a YAML or JSON file.
952+
953+
DJA extends DRF's schema support to generate an OAS schema in the JSON:API format.
954+
955+
### AutoSchema Settings
956+
957+
In order to produce an OAS schema that properly represents the JSON:API structure
958+
you have to either add a `schema` attribute to each view class or set the `REST_FRAMEWORK['DEFAULT_SCHEMA_CLASS']`
959+
to DJA's version of AutoSchema.
960+
961+
You can also extend the OAS schema with additional static content (a feature not available in DRF at this time).
962+
963+
#### View-based
964+
965+
```python
966+
from rest_framework_json_api.schemas.openapi import AutoSchema
967+
968+
class MyViewset(ModelViewSet):
969+
schema = AutoSchema
970+
...
971+
```
972+
973+
#### Default schema class
974+
975+
```python
976+
REST_FRAMEWORK = {
977+
# ...
978+
'DEFAULT_SCHEMA_CLASS': 'rest_framework_json_api.schemas.openapi.AutoSchema',
979+
}
980+
```
981+
982+
### Adding static OAS schema content
983+
984+
You can optionally include an OAS schema document initialization by subclassing `SchemaGenerator`
985+
and setting `schema_init`.
986+
987+
Here's an example that fills out OAS `info` and `servers` objects.
988+
989+
```python
990+
# views.py
991+
992+
from rest_framework_json_api.schemas.openapi import SchemaGenerator as JSONAPISchemaGenerator
993+
994+
995+
class MySchemaGenerator(JSONAPISchemaGenerator):
996+
"""
997+
Describe my OAS schema info in detail and list the servers where it can be found
998+
"""
999+
#: fill in some of the openapi schema
1000+
schema_init = {
1001+
'info': {
1002+
'version': '1.0',
1003+
'title': 'my demo API',
1004+
'description': 'A demonstration of [OAS 3.0](https://www.openapis.org)',
1005+
'contact': {
1006+
'name': 'my name'
1007+
},
1008+
'license': {
1009+
'name': 'BSD 2 clause',
1010+
'url': 'https://github.com/django-json-api/django-rest-framework-json-api/blob/master/LICENSE',
1011+
}
1012+
},
1013+
'servers': [
1014+
{'url': 'https://localhost/v1', 'description': 'local docker'},
1015+
{'url': 'http://localhost:8000/v1', 'description': 'local dev'},
1016+
{'url': 'https://api.example.com/v1', 'description': 'demo server'},
1017+
{'url': '{serverURL}', 'description': 'provide your server URL',
1018+
'variables': {'serverURL': {'default': 'http://localhost:8000/v1'}}}
1019+
]
1020+
}
1021+
```
1022+
1023+
### Generate a Static Schema on Command Line
1024+
1025+
See [DRF documentation for generateschema](https://www.django-rest-framework.org/api-guide/schemas/#generating-a-static-schema-with-the-generateschema-management-command)
1026+
To generate an OAS schema document, use something like:
1027+
1028+
```text
1029+
$ django-admin generateschema --settings=example.settings \
1030+
--generator_class myapp.views.MySchemaGenerator >myschema.yaml
1031+
```
1032+
1033+
You can then use any number of OAS tools such as
1034+
[swagger-ui-watcher](https://www.npmjs.com/package/swagger-ui-watcher)
1035+
to render the schema:
1036+
```text
1037+
$ swagger-ui-watcher myschema.yaml
1038+
```
1039+
1040+
Note: Swagger-ui-watcher will complain that "DELETE operations cannot have a requestBody"
1041+
but it will still work. This [error](https://github.com/OAI/OpenAPI-Specification/pull/2117)
1042+
in the OAS specification will be fixed when [OAS 3.1.0](https://www.openapis.org/blog/2020/06/18/openapi-3-1-0-rc0-its-here)
1043+
is published.
1044+
1045+
([swagger-ui](https://www.npmjs.com/package/swagger-ui) will work silently.)
1046+
1047+
### Generate a Dynamic Schema in a View
1048+
1049+
See [DRF documentation for a Dynamic Schema](https://www.django-rest-framework.org/api-guide/schemas/#generating-a-dynamic-schema-with-schemaview).
1050+
You will need to pass in your custom SchemaGenerator if you've created one.
1051+
1052+
```python
1053+
from rest_framework.schemas import get_schema_view
1054+
from views import MySchemaGenerator
1055+
1056+
urlpatterns = [
1057+
path('openapi', get_schema_view(generator_class=MySchemaGenerator), name='openapi-schema'),
1058+
...
1059+
]
1060+
```
1061+

example/settings/dev.py

+2
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',
@@ -89,6 +90,7 @@
8990
'rest_framework.renderers.BrowsableAPIRenderer',
9091
),
9192
'DEFAULT_METADATA_CLASS': 'rest_framework_json_api.metadata.JSONAPIMetadata',
93+
'DEFAULT_SCHEMA_CLASS': 'rest_framework_json_api.schemas.openapi.AutoSchema',
9294
'DEFAULT_FILTER_BACKENDS': (
9395
'rest_framework_json_api.filters.OrderingFilter',
9496
'rest_framework_json_api.django_filters.DjangoFilterBackend',

example/templates/swagger-ui.html

+30
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>

0 commit comments

Comments
 (0)