Add README and documentation
parent
ed02e3c3a1
commit
207973ae5a
288
README.md
288
README.md
|
|
@ -1 +1,287 @@
|
|||
# drf-swagger
|
||||
# drf-swagger - Yet another Swagger generator for Django Rest Framework
|
||||
|
||||
_**WARNING**: this project is under rapid development; the APIs described here might change at any time without notice_
|
||||
|
||||
## Background
|
||||
|
||||
`OpenAPI 2.0`, 'formerly known as' `Swagger`, is a format designed to encode information about a Web API into an
|
||||
easily parsable schema that can then be used for rendering documentation, generating code, etc.
|
||||
|
||||
More details are available on [swagger.io](https://swagger.io/) and on the
|
||||
[OpenAPI 2.0 specification page](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md).
|
||||
|
||||
From here on, the terms "OpenAPI" and "Swagger" are used interchangeably.
|
||||
|
||||
#### Swagger in Django Rest Framework
|
||||
|
||||
Since Django Rest 3.7, there is now [built in support](http://www.django-rest-framework.org/api-guide/schemas/) for
|
||||
automatic OpenAPI (Swagger) 2.0 schema generation. However, this generation is based on the
|
||||
[coreapi](http://www.coreapi.org/) standard, which for the moment is vastly inferior to OpenAPI in both support and
|
||||
features. In particular, the OpenAPI codec/compatibility layer provided has a few major problems:
|
||||
* there is no support for documenting response schemas and status codes
|
||||
* nested schemas do not work properly
|
||||
* does not handle more complex fields such as `FileField`, `ChoiceField`, ...
|
||||
|
||||
In short this makes the generated schema unusable for code generation, and mediocre at best for documentation.
|
||||
|
||||
#### Third-party libraries
|
||||
There are currently two decent Swagger schema generators that I could find for django-rest-framework:
|
||||
* [django-rest-swagger](https://github.com/marcgibbons/django-rest-swagger)
|
||||
* [drf-openapi](https://github.com/limdauto/drf_openapi)
|
||||
|
||||
Out of the two, `django-rest-swagger` is just a wrapper around DRF 3.7 schema generation with an added UI, and thus has
|
||||
the same problems. `drf-openapi` is a bit more involved and implements some custom handling for response schemas, but
|
||||
ultimately still falls short in code generation because the responses are plain `object`s.
|
||||
|
||||
Both projects are also relatively dead and stagnant.
|
||||
|
||||
|
||||
## Table of contents
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
- [Design](#design)
|
||||
* [Aim](#aim)
|
||||
* [Implementation progress](#implementation-progress)
|
||||
+ [Features](#features)
|
||||
- [Usage](#usage)
|
||||
* [1. Quickstart](#1-quickstart)
|
||||
* [2. Configuration](#2-configuration)
|
||||
- [a. `get_schema_view` parameters](#a-get_schema_view-parameters)
|
||||
- [b. `SchemaView` instantiators](#b-schemaview-instantiators)
|
||||
- [c. `SWAGGER_SETTINGS` and `REDOC_SETTINGS`](#c-swagger_settings-and-redoc_settings)
|
||||
* [3. More customization](#3-more-customization)
|
||||
* [4. Caching](#4-caching)
|
||||
* [5. Validation](#5-validation)
|
||||
+ [`swagger-ui` validation badge](#swagger-ui-validation-badge)
|
||||
- [Online](#online)
|
||||
- [Offline](#offline)
|
||||
+ [using `swagger-cli`](#using-swagger-cli)
|
||||
+ [manually, on `editor.swagger.io`](#manually-on-editorswaggerio)
|
||||
- [Planned feature support](#planned-feature-support)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
## Design
|
||||
|
||||
### Aim
|
||||
This project aims for full compatibility with Swagger/OpenAPI 2.0 code generation tools. More precisely, this means:
|
||||
* support documentation of response schemas for multiple possible status codes
|
||||
* support unbounded schema nesting
|
||||
* generate real OpenAPI Schema definitions instead of inline models
|
||||
* allow easy and pluggable manual overrides for all schema components
|
||||
|
||||
### Implementation progress
|
||||
|
||||
For the first release, most of `django-rest-swagger`'s functionality is implemented. A lot of inspiration and code was
|
||||
drawn from the existing implementations mentioned above, so thanks are due to their respective authors.
|
||||
|
||||
#### Features
|
||||
* schema generation is a wrapper around coreapi & drf
|
||||
* bundled latest version of [swagger-ui](https://github.com/swagger-api/swagger-ui) and
|
||||
[redoc](https://github.com/Rebilly/ReDoc)
|
||||
* supports dumping of schema in JSON and YAML
|
||||
* schema view is cacheable out of the box
|
||||
* generated Swagger schema can be automatically validated by [flex](https://github.com/pipermerriam/flex) or
|
||||
[swagger-spec-validator](https://github.com/Yelp/swagger_spec_validator)
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
### 1. Quickstart
|
||||
In `settings.py`:
|
||||
```python
|
||||
|
||||
INSTALLED_APPS = [
|
||||
...
|
||||
'drf_swagger',
|
||||
...
|
||||
]
|
||||
```
|
||||
|
||||
In `urls.py`:
|
||||
```python
|
||||
...
|
||||
from drf_swagger.views import get_schema_view
|
||||
from drf_swagger import openapi
|
||||
|
||||
...
|
||||
|
||||
schema_view = get_schema_view(
|
||||
openapi.Info(
|
||||
title="Snippets API",
|
||||
default_version='v1',
|
||||
description="Test description",
|
||||
terms_of_service="https://www.google.com/policies/terms/",
|
||||
contact=openapi.Contact(email="contact@snippets.local"),
|
||||
license=openapi.License(name="BSD License"),
|
||||
),
|
||||
validators=['flex', 'ssv'],
|
||||
public=False,
|
||||
permission_classes=(permissions.AllowAny,),
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^swagger(?P<format>.json|.yaml)$', schema_view.without_ui(cache_timeout=None), name='schema-json'),
|
||||
url(r'^swagger/$', schema_view.with_ui('swagger', cache_timeout=None), name='schema-swagger-ui'),
|
||||
url(r'^redoc/$', schema_view.with_ui('redoc', cache_timeout=None), name='schema-redoc'),
|
||||
...
|
||||
]
|
||||
```
|
||||
|
||||
You've just created:
|
||||
* A JSON view of your schema at `/swagger.json`
|
||||
* A YAML view of your schema at `/swagger.yaml`
|
||||
* A swagger-ui view of your schema at `/swagger/`
|
||||
* A ReDoc view of your schema at `/redoc/`
|
||||
|
||||
### 2. Configuration
|
||||
##### a. `get_schema_view` parameters
|
||||
* `info` - Required. Swagger API Info object
|
||||
* `url` - API base url; if left blank will be deduced from the location the view is served at
|
||||
* `patterns` - passed to SchemaGenerator
|
||||
* `urlconf` - passed to SchemaGenerator
|
||||
* `public` - if False, includes only endpoints the current user has access to
|
||||
* `validators` - a list of validator names to apply on the generated schema; allowed values are `flex`, `ssv`
|
||||
* `authentication_classes` - authentication classes for the schema view itself
|
||||
* `permission_classes` - permission classes for the schema view itself
|
||||
|
||||
##### b. `SchemaView` instantiators
|
||||
* `SchemaView.with_ui(renderer, ...)` - get a view instance using the specified UI renderer; one of `swagger`, `redoc`
|
||||
* `SchemaView.without_ui(...)` - get a view instance with no UI renderer; same as `as_cached_view` with no kwargs
|
||||
* `SchemaView.as_cached_view(...)` - same as `as_view`, but with optional caching
|
||||
* you can, of course, call `as_view` as usual
|
||||
|
||||
All of the first 3 methods take two optional arguments, `cache_timeout` and `cache_kwargs`; if present, these are
|
||||
passed on to Django's `cached_page` decorator in order to enable caching on the resulting viewl.
|
||||
See [4. Caching](#4-caching).
|
||||
|
||||
|
||||
##### c. `SWAGGER_SETTINGS` and `REDOC_SETTINGS`
|
||||
Additionally, you can include some more settings in your `settings.py` file.
|
||||
The possible settings and their default values are as follows:
|
||||
|
||||
```python
|
||||
SWAGGER_SETTINGS = {
|
||||
'USE_SESSION_AUTH': True, # add Django Login and Django Logout buttons, CSRF token to swagger UI page
|
||||
'LOGIN_URL': getattr(django.conf.settings, 'LOGIN_URL', None), # URL for the login button
|
||||
'LOGOUT_URL': getattr(django.conf.settings, 'LOGOUT_URL', None), # URL for the logout button
|
||||
|
||||
# Swagger security definitions to include in the schema;
|
||||
# see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-definitions-object
|
||||
'SECURITY_DEFINITIONS': {
|
||||
'basic': {
|
||||
'type': 'basic'
|
||||
}
|
||||
},
|
||||
|
||||
# url to an external Swagger validation service; defaults to 'http://online.swagger.io/validator/'
|
||||
# set to None to disable the schema validation badge in the UI
|
||||
'VALIDATOR_URL': '',
|
||||
|
||||
# swagger-ui configuration settings, see https://github.com/swagger-api/swagger-ui#parameters of the same name
|
||||
'OPERATIONS_SORTER': None,
|
||||
'TAGS_SORTER': None,
|
||||
'DOC_EXPANSION': 'list',
|
||||
'DEEP_LINKING': False,
|
||||
'SHOW_EXTENSIONS': True,
|
||||
'DEFAULT_MODEL_RENDERING': 'model',
|
||||
'DEFAULT_MODEL_DEPTH': 2,
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
REDOC_SETTINGS = {
|
||||
# ReDoc UI configuration settings, see https://github.com/Rebilly/ReDoc#redoc-tag-attributes
|
||||
'LAZY_RENDERING': True,
|
||||
'HIDE_HOSTNAME': False,
|
||||
'EXPAND_RESPONSES': 'all',
|
||||
'PATH_IN_MIDDLE': False,
|
||||
}
|
||||
```
|
||||
|
||||
### 3. More customization
|
||||
Should you have need of more fine-grained customization over the schema view and generation, you are on your own to
|
||||
figure out where you need to subclass and plug your functionality. Here are a few high-level hints:
|
||||
|
||||
* `OpenAPISchemaGenerator` enumerates all the API endpoints registered in Django Rest Framework, inspects their view
|
||||
classes and generates an appropriate `Swagger` object describing the API structure
|
||||
* `SchemaView` gets a `drf_swagger.openapi.Swagger` schema object from a generator and renders it into an HTTP response
|
||||
* you can subclass `SchemaView` by extending the return value of `get_schema_view`, e.g.:
|
||||
```python
|
||||
SchemaView = get_schema_view(info, ...)
|
||||
|
||||
class CustomSchemaView(SchemaView):
|
||||
generator_class = CustomSchemaGenerator
|
||||
renderer_classes = (CustomRenderer1, CustomRenderer2,)
|
||||
```
|
||||
|
||||
* `drf_swagger.renderers` take a `Swagger` object and transform it into an OpenAPI 2.0 specification document
|
||||
using `OpenAPICodecJson`, `OpenAPICodecYaml`, or into a web interface using an OpenAPI renderer library.
|
||||
* `drf_swagger.codecs` take a `Swagger` object and encode it in an exportable format (json or yaml by default).
|
||||
|
||||
### 4. Caching
|
||||
Since the schema does not usually change during the lifetime of the django process, there is out of the box support
|
||||
for caching the schema view in-memory, with some sane defaults:
|
||||
* caching is enabled by the [`cache_page`](https://docs.djangoproject.com/en/1.11/topics/cache/#the-per-view-cache)
|
||||
decorator, using the default Django cache backend but this can be changed using the `cache_kwargs` argument
|
||||
* HTTP caching of the response is blocked to avoid confusing situations caused by being served stale schemas
|
||||
* the cached schema varies on the `Cookie` and `Authorization` HTTP headers to enable filtering of visible endpoints
|
||||
according to the authentication credentials of each user; note that this means that every user accessing the schema
|
||||
will have a separate schema cached in memory.
|
||||
|
||||
### 5. Validation
|
||||
Given the numerous methods to manually customzie the generated schema, it makes sense to validate the result to ensure
|
||||
it still conforms to OpenAPI 2.0. To this end, validation is provided at the generation point using python swagger
|
||||
libraries, and can be activated by passing `validators=['flex', 'ssv']` to get_schema_view; if the generated schema
|
||||
is not valid, a `SwaggerValidationError` is raised by the handling codec and nothing is returned.
|
||||
|
||||
**Warning:** This internal validation is quite slow and can be a DOS vector if left activated on a publicly available view.
|
||||
|
||||
Caching can mitigate the speed impact of validation on restricted views.
|
||||
|
||||
The provided validation will catch syntactic errors, but more subtle violations of the spec might slip by them. To
|
||||
ensure compatibility with code generation tools, it is recommended to also employ one or more of the following methods:
|
||||
- #### `swagger-ui` validation badge
|
||||
|
||||
##### Online
|
||||
If your schema is publicly accessible, `swagger-ui` will automatically validate it against the official swagger
|
||||
online validator and display the result in the bottom-right validation badge.
|
||||
##### Offline
|
||||
If your schema is not accessible from the internet, you can run a local copy of
|
||||
[swagger-validator](https://hub.docker.com/r/swaggerapi/swagger-validator/) and set the `VALIDATOR_URL` accordingly:
|
||||
```python
|
||||
SWAGGER_SETTINGS = {
|
||||
...
|
||||
'VALIDATOR_URL': 'http://localhost:8189',
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker run --name swagger-validator -d -p 8189:8080 --add-host test.local:10.0.75.1 swaggerapi/swagger-validator
|
||||
84dabd52ba967c32ae6b660934fa6a429ca6bc9e594d56e822a858b57039c8a2
|
||||
$ curl http://localhost:8189/debug?url=http://test.local:8002/swagger/?format=openapi
|
||||
{}
|
||||
```
|
||||
|
||||
- #### using `swagger-cli`
|
||||
[https://www.npmjs.com/package/swagger-cli](https://www.npmjs.com/package/swagger-cli)
|
||||
```bash
|
||||
$ npm install -g swagger-cli
|
||||
[...]
|
||||
$ swagger-cli validate http://test.local:8002/swagger.yaml
|
||||
http://test.local:8002/swagger.yaml is valid
|
||||
```
|
||||
|
||||
- #### manually, on `editor.swagger.io`
|
||||
Importing the generated spec into [https://editor.swagger.io/](https://editor.swagger.io/) will automatically
|
||||
trigger validation on it.
|
||||
|
||||
|
||||
## Planned feature support
|
||||
* **OpenAPI 3.0** - if I get 2.0 working like I want, and it's not too hard to adapt to 3.0
|
||||
|
|
@ -10,8 +10,8 @@ SWAGGER_DEFAULTS = {
|
|||
},
|
||||
'LOGIN_URL': getattr(settings, 'LOGIN_URL', None),
|
||||
'LOGOUT_URL': getattr(settings, 'LOGOUT_URL', None),
|
||||
|
||||
'VALIDATOR_URL': '',
|
||||
|
||||
'OPERATIONS_SORTER': None,
|
||||
'TAGS_SORTER': None,
|
||||
'DOC_EXPANSION': 'list',
|
||||
|
|
|
|||
|
|
@ -5,6 +5,13 @@ import coreapi
|
|||
|
||||
|
||||
class Contact(object):
|
||||
"""Swagger Contact object
|
||||
At least one of the following fields is required:
|
||||
|
||||
:param str name: contact name
|
||||
:param str url: contact url
|
||||
:param str email: contact e-mail
|
||||
"""
|
||||
def __init__(self, name=None, url=None, email=None):
|
||||
self.name = name
|
||||
self.url = url
|
||||
|
|
@ -25,6 +32,11 @@ class Contact(object):
|
|||
|
||||
|
||||
class License(object):
|
||||
"""Swagger License object
|
||||
|
||||
:param str name: Requird. License name
|
||||
:param str url: link to detailed license information
|
||||
"""
|
||||
def __init__(self, name, url=None):
|
||||
self.name = name
|
||||
self.url = url
|
||||
|
|
@ -41,6 +53,15 @@ class License(object):
|
|||
|
||||
|
||||
class Info(object):
|
||||
"""Swagger Info object
|
||||
|
||||
:param str title: Required. API title.
|
||||
:param str default_version: Required. API version string (not to be confused with Swagger spec version)
|
||||
:param str description: API description; markdown supported
|
||||
:param str terms_of_service: API terms of service; should be a URL
|
||||
:param Contact contact: contact object
|
||||
:param License license: license object
|
||||
"""
|
||||
def __init__(self, title, default_version, description=None, terms_of_service=None, contact=None, license=None):
|
||||
if title is None or default_version is None:
|
||||
raise ValueError("title and version are required for Swagger info object")
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<script id="redoc-settings">{{ swagger_settings | safe }}</script>
|
||||
<script>
|
||||
var currentPath = window.location.protocol + "//" + window.location.host + window.location.pathname;
|
||||
var specURL = currentPath + '?format=openapi';
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@
|
|||
}
|
||||
window.ui = SwaggerUIBundle(swaggerConfig);
|
||||
|
||||
insertionQ('.auth-wrapper .authorize').every(function (element) {
|
||||
insertionQ('.auth-wrapper .authorize').every(function () {
|
||||
var authWrapper = document.querySelector('.auth-wrapper');
|
||||
var authorizeButton = document.querySelector('.auth-wrapper .authorize');
|
||||
var djangoSessionAuth = document.querySelector('#django-session-auth');
|
||||
|
|
|
|||
|
|
@ -14,12 +14,9 @@ from .generators import OpenAPISchemaGenerator
|
|||
from .renderers import (
|
||||
SwaggerJSONRenderer, SwaggerYAMLRenderer, SwaggerUIRenderer, ReDocRenderer, OpenAPIRenderer,
|
||||
)
|
||||
from .openapi import Info
|
||||
|
||||
SPEC_RENDERERS = (SwaggerYAMLRenderer, SwaggerJSONRenderer, OpenAPIRenderer)
|
||||
SPEC_RENDERERS = {
|
||||
False: tuple(renderer.with_validators([]) for renderer in SPEC_RENDERERS),
|
||||
True: SPEC_RENDERERS,
|
||||
}
|
||||
UI_RENDERERS = {
|
||||
'swagger': (SwaggerUIRenderer, ReDocRenderer),
|
||||
'redoc': (ReDocRenderer, SwaggerUIRenderer),
|
||||
|
|
@ -50,41 +47,57 @@ def deferred_never_cache(view_func):
|
|||
return _wrapped_view_func
|
||||
|
||||
|
||||
def get_schema_view(info, url=None, patterns=None, urlconf=None, *, public=False, validate=False,
|
||||
def get_schema_view(info, url=None, patterns=None, urlconf=None, *, public=False, validators=None,
|
||||
authentication_classes=api_settings.DEFAULT_AUTHENTICATION_CLASSES,
|
||||
permission_classes=api_settings.DEFAULT_PERMISSION_CLASSES):
|
||||
"""
|
||||
Create a SchemaView class with default renderers and generators.
|
||||
|
||||
:param Info info: Required. Swagger API Info object
|
||||
:param str url: API base url; if left blank will be deduced from the location the view is served at
|
||||
:param str patterns: passed to SchemaGenerator
|
||||
:param str urlconf: passed to SchemaGenerator
|
||||
:param bool public: if False, includes only endpoints the current user has access to
|
||||
:param list validators: a list of validator names to apply on the generated schema; allowed values are `flex`, `ssv`
|
||||
:param tuple authentication_classes: authentication classes for the schema view itself
|
||||
:param tuple permission_classes: permission classes for the schema view itself
|
||||
:return: SchemaView class
|
||||
"""
|
||||
_auth_classes = authentication_classes
|
||||
_perm_classes = permission_classes
|
||||
_public = public
|
||||
validators = validators or []
|
||||
_spec_renderers = tuple(renderer.with_validators(validators) for renderer in SPEC_RENDERERS)
|
||||
|
||||
class SchemaView(APIView):
|
||||
_ignore_model_permissions = True
|
||||
schema = None # exclude from schema
|
||||
public = _public
|
||||
generator_class = OpenAPISchemaGenerator
|
||||
authentication_classes = _auth_classes
|
||||
permission_classes = _perm_classes
|
||||
renderer_classes = SPEC_RENDERERS[bool(validate)]
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(SchemaView, self).__init__(**kwargs)
|
||||
if self.renderer_classes is None:
|
||||
if renderers.BrowsableAPIRenderer in api_settings.DEFAULT_RENDERER_CLASSES:
|
||||
self.renderer_classes = [
|
||||
renderers.CoreJSONRenderer,
|
||||
renderers.BrowsableAPIRenderer,
|
||||
]
|
||||
else:
|
||||
self.renderer_classes = [renderers.CoreJSONRenderer]
|
||||
renderer_classes = _spec_renderers
|
||||
|
||||
def get(self, request, version='', format=None):
|
||||
generator = OpenAPISchemaGenerator(info, version, url, patterns, urlconf)
|
||||
generator = self.generator_class(info, version, url, patterns, urlconf)
|
||||
schema = generator.get_schema(request, self.public)
|
||||
if schema is None:
|
||||
raise exceptions.PermissionDenied()
|
||||
return Response(schema)
|
||||
|
||||
@classmethod
|
||||
def _cached(cls, view, cache_timeout, cache_kwargs):
|
||||
def as_cached_view(cls, cache_timeout=0, cache_kwargs=None, **initkwargs):
|
||||
"""
|
||||
Calls .as_view() and wraps the result in a cache_page decorator.
|
||||
See https://docs.djangoproject.com/en/1.11/topics/cache/
|
||||
|
||||
:param int cache_timeout: same as cache_page; set to 0 for no cache
|
||||
:param dict cache_kwargs: dictionary of kwargs to be passed to cache_page
|
||||
:param initkwargs: kwargs for .as_view()
|
||||
:return: a view instance
|
||||
"""
|
||||
cache_kwargs = cache_kwargs or {}
|
||||
view = cls.as_view(**initkwargs)
|
||||
if cache_timeout != 0:
|
||||
view = vary_on_headers('Cookie', 'Authorization', 'Accept')(view)
|
||||
view = cache_page(cache_timeout, **cache_kwargs)(view)
|
||||
|
|
@ -94,20 +107,31 @@ def get_schema_view(info, url=None, patterns=None, urlconf=None, *, public=False
|
|||
return view
|
||||
|
||||
@classmethod
|
||||
def as_cached_view(cls, cache_timeout=0, **cache_kwargs):
|
||||
return cls._cached(cls.as_view(), cache_timeout, cache_kwargs)
|
||||
def without_ui(cls, cache_timeout=0, cache_kwargs=None):
|
||||
"""
|
||||
Instantiate this view with just JSON and YAML renderers, optionally wrapped with cache_page.
|
||||
See https://docs.djangoproject.com/en/1.11/topics/cache/.
|
||||
|
||||
:param int cache_timeout: same as cache_page; set to 0 for no cache
|
||||
:param dict cache_kwargs: dictionary of kwargs to be passed to cache_page
|
||||
:return: a view instance
|
||||
"""
|
||||
return cls.as_cached_view(cache_timeout, cache_kwargs, renderer_classes=_spec_renderers)
|
||||
|
||||
@classmethod
|
||||
def without_ui(cls, cache_timeout=0, **cache_kwargs):
|
||||
renderer_classes = SPEC_RENDERERS[bool(validate)]
|
||||
return cls._cached(cls.as_view(renderer_classes=renderer_classes), cache_timeout, cache_kwargs)
|
||||
def with_ui(cls, renderer='swagger', cache_timeout=0, cache_kwargs=None):
|
||||
"""
|
||||
Instantiate this view with a Web UI renderer, optionally wrapped with cache_page.
|
||||
See https://docs.djangoproject.com/en/1.11/topics/cache/.
|
||||
|
||||
@classmethod
|
||||
def with_ui(cls, renderer='swagger', cache_timeout=0, **cache_kwargs):
|
||||
:param str renderer: UI renderer; allowed values are `swagger`, `redoc`
|
||||
:param int cache_timeout: same as cache_page; set to 0 for no cache
|
||||
:param dict cache_kwargs: dictionary of kwargs to be passed to cache_page
|
||||
:return: a view instance
|
||||
"""
|
||||
assert renderer in UI_RENDERERS, "supported default renderers are " + ", ".join(UI_RENDERERS)
|
||||
renderer_classes = (*UI_RENDERERS[renderer], *SPEC_RENDERERS[bool(validate)])
|
||||
renderer_classes = (*UI_RENDERERS[renderer], *_spec_renderers)
|
||||
|
||||
view = cls.as_view(renderer_classes=renderer_classes)
|
||||
return cls._cached(view, cache_timeout, cache_kwargs)
|
||||
return cls.as_cached_view(cache_timeout, cache_kwargs, renderer_classes=renderer_classes)
|
||||
|
||||
return SchemaView
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
{
|
||||
"name": "drf-swagger",
|
||||
"dependencies": {
|
||||
"redoc": "^2.0.0-alpha.4",
|
||||
"swagger-ui-dist": "^3.5.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
pygments>=2.2.0
|
||||
django-cors-headers>=2.1.0
|
||||
|
|
@ -1 +0,0 @@
|
|||
pygments>=2.2.0
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
5
setup.py
5
setup.py
|
|
@ -10,13 +10,16 @@ def read_req(req_file):
|
|||
|
||||
requirements = read_req('requirements.txt')
|
||||
requirements_validation = read_req('requirements_validation.txt')
|
||||
|
||||
requirements_dev = read_req('requirements_dev.txt')
|
||||
requirements_test = read_req('requirements_test.txt')
|
||||
0
|
||||
setup(
|
||||
name='drf-swagger',
|
||||
version='1.0.0rc1',
|
||||
packages=find_packages(include=['drf_swagger']),
|
||||
include_package_data=True,
|
||||
install_requires=requirements,
|
||||
tests_require=requirements_test,
|
||||
extras_require={
|
||||
'validation': requirements_validation
|
||||
},
|
||||
|
|
|
|||
|
|
@ -24,11 +24,6 @@ class SnippetSerializer(serializers.Serializer):
|
|||
lines = serializers.ListField(child=serializers.IntegerField(), allow_empty=True, allow_null=True, required=False)
|
||||
example_projects = serializers.ListSerializer(child=ExampleProjectsSerializer())
|
||||
|
||||
class Meta:
|
||||
error_status_codes = {
|
||||
HTTP_400_BAD_REQUEST: 'Bad Request'
|
||||
}
|
||||
|
||||
def create(self, validated_data):
|
||||
"""
|
||||
Create and return a new `Snippet` instance, given the validated data.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import os
|
|||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
|
||||
|
||||
|
|
@ -13,8 +12,10 @@ SECRET_KEY = '!z1yj(9uz)zk0gg@5--j)bc4h^i!8))r^dezco8glf190e0&#p'
|
|||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
ALLOWED_HOSTS = [
|
||||
'test.local'
|
||||
]
|
||||
CORS_ORIGIN_ALLOW_ALL = True
|
||||
|
||||
# Application definition
|
||||
|
||||
|
|
@ -26,12 +27,14 @@ INSTALLED_APPS = [
|
|||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'rest_framework',
|
||||
'corsheaders',
|
||||
|
||||
'drf_swagger',
|
||||
'snippets'
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
|
|
@ -61,7 +64,6 @@ TEMPLATES = [
|
|||
|
||||
WSGI_APPLICATION = 'testproj.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
|
||||
|
||||
|
|
@ -72,7 +74,6 @@ DATABASES = {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
|
||||
|
||||
|
|
@ -91,6 +92,11 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||
},
|
||||
]
|
||||
|
||||
SWAGGER_SETTINGS = {
|
||||
'LOGIN_URL': '/admin/login',
|
||||
'LOGOUT_URL': '/admin/logout',
|
||||
'VALIDATOR_URL': 'http://localhost:8189',
|
||||
}
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.11/topics/i18n/
|
||||
|
|
@ -105,12 +111,7 @@ USE_L10N = True
|
|||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.11/howto/static-files/
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ schema_view = get_schema_view(
|
|||
title="Snippets API",
|
||||
default_version='v1',
|
||||
description="Test description",
|
||||
terms_of_service="*Some TOS*",
|
||||
contact=openapi.Contact(email="cristi@cvjd.me"),
|
||||
license=openapi.License("BSD License"),
|
||||
terms_of_service="https://www.google.com/policies/terms/",
|
||||
contact=openapi.Contact(email="contact@snippets.local"),
|
||||
license=openapi.License(name="BSD License"),
|
||||
),
|
||||
validate=True,
|
||||
validators=['flex', 'ssv'],
|
||||
public=False,
|
||||
permission_classes=(permissions.AllowAny,),
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue