Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9113ca0

Browse files
keyz182n2ygksliverc
authored
OAS 3.0 schema generation (#772)
initial implementation of OAS 3.0 generateschema Co-authored-by: Alan Crosswell <alan@columbia.edu> Co-authored-by: Oliver Sauder <sliverc@users.noreply.github.com>
1 parent b192cb0 commit 9113ca0

File tree

18 files changed

+1910
-7
lines changed

18 files changed

+1910
-7
lines changed

‎AUTHORS‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Jason Housley <housleyjk@gmail.com>
1414
Jerel Unruh <mail@unruhdesigns.com>
1515
Jonathan Senecal <contact@jonathansenecal.com>
1616
Joseba Mendivil <git@jma.email>
17+
Kieran Evans <keyz182@gmail.com>
1718
Léo S. <leo@naeka.fr>
1819
Luc Cary <luc.cary@gmail.com>
1920
Matt Layman <https://www.mattlayman.com>

‎CHANGELOG.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,17 @@ This release is not backwards compatible. For easy migration best upgrade first
1818
* Added support for Django REST framework 3.12
1919
* Added support for Django 3.1
2020
* Added support for Python 3.9
21+
* Added initial optional support for [openapi](https://www.openapis.org/) schema generation. Enable with:
22+
```
23+
pip install djangorestframework-jsonapi['openapi']
24+
```
25+
This first release is a start at implementing OAS schema generation. To use the generated schema you may
26+
still need to manually add some schema attributes but can expect future improvements here and as
27+
upstream DRF's OAS schema generation continues to mature.
2128

2229
### Removed
2330

31+
2432
* Removed support for Python 3.5.
2533
* Removed support for Django 1.11.
2634
* Removed support for Django 2.1.

‎README.rst‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ From PyPI
108108
$ # for optional package integrations
109109
$ pip install djangorestframework-jsonapi['django-filter']
110110
$ pip install djangorestframework-jsonapi['django-polymorphic']
111+
$ pip install djangorestframework-jsonapi['openapi']
111112

112113

113114
From Source
@@ -135,7 +136,10 @@ installed and activated:
135136
$ django-admin loaddata drf_example --settings=example.settings
136137
$ django-admin runserver --settings=example.settings
137138

138-
Browse to http://localhost:8000
139+
Browse to
140+
* http://localhost:8000 for the list of available collections (in a non-JSONAPI format!),
141+
* http://localhost:8000/swagger-ui/ for a Swagger user interface to the dynamic schema view, or
142+
* http://localhost:8000/openapi for the schema view's OpenAPI specification document.
139143

140144

141145
Running Tests and linting

‎docs/getting-started.md‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ From PyPI
6767
# for optional package integrations
6868
pip install djangorestframework-jsonapi['django-filter']
6969
pip install djangorestframework-jsonapi['django-polymorphic']
70+
pip install djangorestframework-jsonapi['openapi']
7071

7172
From Source
7273

@@ -85,7 +86,10 @@ From Source
8586
django-admin runserver --settings=example.settings
8687

8788

88-
Browse to http://localhost:8000
89+
Browse to
90+
* [http://localhost:8000](http://localhost:8000) for the list of available collections (in a non-JSONAPI format!),
91+
* [http://localhost:8000/swagger-ui/](http://localhost:8000/swagger-ui/) for a Swagger user interface to the dynamic schema view, or
92+
* [http://localhost:8000/openapi](http://localhost:8000/openapi) for the schema view's OpenAPI specification document.
8993

9094
## Running Tests
9195

‎docs/usage.md‎

Lines changed: 122 additions & 1 deletion
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,124 @@ 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+
#### View-based
962+
963+
```python
964+
from rest_framework_json_api.schemas.openapi import AutoSchema
965+
966+
class MyViewset(ModelViewSet):
967+
schema = AutoSchema
968+
...
969+
```
970+
971+
#### Default schema class
972+
973+
```python
974+
REST_FRAMEWORK = {
975+
# ...
976+
'DEFAULT_SCHEMA_CLASS': 'rest_framework_json_api.schemas.openapi.AutoSchema',
977+
}
978+
```
979+
980+
### Adding additional OAS schema content
981+
982+
You can extend the OAS schema document by subclassing
983+
[`SchemaGenerator`](https://www.django-rest-framework.org/api-guide/schemas/#schemagenerator)
984+
and extending `get_schema`.
985+
986+
987+
Here's an example that adds OAS `info` and `servers` objects.
988+
989+
```python
990+
from rest_framework_json_api.schemas.openapi import SchemaGenerator as JSONAPISchemaGenerator
991+
992+
993+
class MySchemaGenerator(JSONAPISchemaGenerator):
994+
"""
995+
Describe my OAS schema info in detail (overriding what DRF put in) and list the servers where it can be found.
996+
"""
997+
def get_schema(self, request, public):
998+
schema = super().get_schema(request, public)
999+
schema['info'] = {
1000+
'version': '1.0',
1001+
'title': 'my demo API',
1002+
'description': 'A demonstration of [OAS 3.0](https://www.openapis.org)',
1003+
'contact': {
1004+
'name': 'my name'
1005+
},
1006+
'license': {
1007+
'name': 'BSD 2 clause',
1008+
'url': 'https://github.com/django-json-api/django-rest-framework-json-api/blob/master/LICENSE',
1009+
}
1010+
}
1011+
schema['servers'] = [
1012+
{'url': 'https://localhost/v1', 'description': 'local docker'},
1013+
{'url': 'http://localhost:8000/v1', 'description': 'local dev'},
1014+
{'url': 'https://api.example.com/v1', 'description': 'demo server'},
1015+
{'url': '{serverURL}', 'description': 'provide your server URL',
1016+
'variables': {'serverURL': {'default': 'http://localhost:8000/v1'}}}
1017+
]
1018+
return schema
1019+
```
1020+
1021+
### Generate a Static Schema on Command Line
1022+
1023+
See [DRF documentation for generateschema](https://www.django-rest-framework.org/api-guide/schemas/#generating-a-static-schema-with-the-generateschema-management-command)
1024+
To generate an OAS schema document, use something like:
1025+
1026+
```text
1027+
$ django-admin generateschema --settings=example.settings \
1028+
--generator_class myapp.views.MySchemaGenerator >myschema.yaml
1029+
```
1030+
1031+
You can then use any number of OAS tools such as
1032+
[swagger-ui-watcher](https://www.npmjs.com/package/swagger-ui-watcher)
1033+
to render the schema:
1034+
```text
1035+
$ swagger-ui-watcher myschema.yaml
1036+
```
1037+
1038+
Note: Swagger-ui-watcher will complain that "DELETE operations cannot have a requestBody"
1039+
but it will still work. This [error](https://github.com/OAI/OpenAPI-Specification/pull/2117)
1040+
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)
1041+
is published.
1042+
1043+
([swagger-ui](https://www.npmjs.com/package/swagger-ui) will work silently.)
1044+
1045+
### Generate a Dynamic Schema in a View
1046+
1047+
See [DRF documentation for a Dynamic Schema](https://www.django-rest-framework.org/api-guide/schemas/#generating-a-dynamic-schema-with-schemaview).
1048+
1049+
```python
1050+
from rest_framework.schemas import get_schema_view
1051+
1052+
urlpatterns = [
1053+
...
1054+
path('openapi', get_schema_view(
1055+
title="Example API",
1056+
description="API for all things ...",
1057+
version="1.0.0",
1058+
generator_class=MySchemaGenerator,
1059+
), name='openapi-schema'),
1060+
path('swagger-ui/', TemplateView.as_view(
1061+
template_name='swagger-ui.html',
1062+
extra_context={'schema_url': 'openapi-schema'}
1063+
), name='swagger-ui'),
1064+
...
1065+
]
1066+
```
1067+

‎example/serializers.py‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,16 @@ class AuthorSerializer(serializers.ModelSerializer):
230230
queryset=Comment.objects,
231231
many=True
232232
)
233+
secrets = serializers.HiddenField(
234+
default='Shhhh!'
235+
)
236+
defaults = serializers.CharField(
237+
default='default',
238+
max_length=20,
239+
min_length=3,
240+
write_only=True,
241+
help_text='help for defaults',
242+
)
233243
included_serializers = {
234244
'bio': AuthorBioSerializer,
235245
'type': AuthorTypeSerializer
@@ -244,7 +254,8 @@ class AuthorSerializer(serializers.ModelSerializer):
244254

245255
class Meta:
246256
model = Author
247-
fields = ('name', 'email', 'bio', 'entries', 'comments', 'first_entry', 'type')
257+
fields = ('name', 'email', 'bio', 'entries', 'comments', 'first_entry', 'type',
258+
'secrets', 'defaults')
248259

249260
def get_first_entry(self, obj):
250261
return obj.entries.first()

‎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: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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" type="text/css" href="//unpkg.com/swagger-ui-dist@3/swagger-ui.css" />
8+
</head>
9+
<body>
10+
<div id="swagger-ui"></div>
11+
<script src="//unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js"></script>
12+
<script>
13+
const ui = SwaggerUIBundle({
14+
url: "{% url schema_url %}",
15+
dom_id: '#swagger-ui',
16+
presets: [
17+
SwaggerUIBundle.presets.apis,
18+
SwaggerUIBundle.SwaggerUIStandalonePreset
19+
],
20+
layout: "BaseLayout",
21+
requestInterceptor: (request) => {
22+
request.headers['X-CSRFToken'] = "{{ csrf_token }}"
23+
return request;
24+
}
25+
})
26+
</script>
27+
</body>
28+
</html>

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /