Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 68b0dda0b9 | |||
| f81795d745 | |||
| caa397b906 | |||
| faf81e7b6d | |||
| 74fcd47047 | |||
| 02b72c466e | |||
| 10deea826d | |||
| bbdc37a45e |
+2
-2
@@ -1,4 +1,6 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
|
testproj/db.sqlite3
|
||||||
|
.vscode/
|
||||||
|
|
||||||
# Created by .ignore support plugin (hsz.mobi)
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
### Python template
|
### Python template
|
||||||
@@ -156,5 +158,3 @@ com_crashlytics_export_strings.xml
|
|||||||
crashlytics.properties
|
crashlytics.properties
|
||||||
crashlytics-build.properties
|
crashlytics-build.properties
|
||||||
fabric.properties
|
fabric.properties
|
||||||
|
|
||||||
testproj/db\.sqlite3
|
|
||||||
|
|||||||
+2
-2
@@ -36,7 +36,7 @@ You want to contribute some code? Great! Here are a few steps to get you started
|
|||||||
$ virtualenv venv
|
$ virtualenv venv
|
||||||
$ source venv/bin/activate
|
$ source venv/bin/activate
|
||||||
(venv) $ pip install -e .[validation]
|
(venv) $ pip install -e .[validation]
|
||||||
(venv) $ pip install -rrequirements/dev.txt -rrequirements/test.txt
|
(venv) $ pip install -rrequirements/dev.txt -rrequirements/test.txt "Django>=1.11.7"
|
||||||
|
|
||||||
#. **Make your changes and check them against the test project**
|
#. **Make your changes and check them against the test project**
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ You want to contribute some code? Great! Here are a few steps to get you started
|
|||||||
|
|
||||||
(venv) $ cd testproj
|
(venv) $ cd testproj
|
||||||
(venv) $ python manage.py migrate
|
(venv) $ python manage.py migrate
|
||||||
(venv) $ cat createsuperuser.py | python manage.py shell
|
(venv) $ python manage.py shell -c "import createsuperuser"
|
||||||
(venv) $ python manage.py runserver
|
(venv) $ python manage.py runserver
|
||||||
(venv) $ firefox localhost:8000/swagger/
|
(venv) $ firefox localhost:8000/swagger/
|
||||||
|
|
||||||
|
|||||||
+27
-7
@@ -29,12 +29,12 @@ Features
|
|||||||
- customization hooks at all points in the spec generation process
|
- customization hooks at all points in the spec generation process
|
||||||
- JSON and YAML format for spec
|
- JSON and YAML format for spec
|
||||||
- bundles latest version of
|
- bundles latest version of
|
||||||
`swagger-ui <https://github.com/swagger-api/swagger-ui>`__ and
|
`swagger-ui <https://github.com/swagger-api/swagger-ui>`_ and
|
||||||
`redoc <https://github.com/Rebilly/ReDoc>`__ for viewing the generated documentation
|
`redoc <https://github.com/Rebilly/ReDoc>`_ for viewing the generated documentation
|
||||||
- schema view is cacheable out of the box
|
- schema view is cacheable out of the box
|
||||||
- generated Swagger schema can be automatically validated by
|
- generated Swagger schema can be automatically validated by
|
||||||
`swagger-spec-validator <https://github.com/Yelp/swagger_spec_validator>`__ or
|
`swagger-spec-validator <https://github.com/Yelp/swagger_spec_validator>`_ or
|
||||||
`flex <https://github.com/pipermerriam/flex>`__
|
`flex <https://github.com/pipermerriam/flex>`_
|
||||||
|
|
||||||
.. figure:: https://raw.githubusercontent.com/axnsan12/drf-yasg/1.0.2/screenshots/redoc-nested-response.png
|
.. figure:: https://raw.githubusercontent.com/axnsan12/drf-yasg/1.0.2/screenshots/redoc-nested-response.png
|
||||||
:width: 100%
|
:width: 100%
|
||||||
@@ -251,9 +251,9 @@ 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>`__
|
* 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, can be changed using the ``cache_kwargs`` argument
|
decorator, using the default Django cache backend, can be changed using the ``cache_kwargs`` argument
|
||||||
* HTTP caching of the response is blocked to avoid confusing situations caused by being shown stale schemas
|
* HTTP caching of the response is blocked to avoid confusing situations caused by being shown stale schemas
|
||||||
* if `public` is set to ``False`` on the SchemaView, the cached schema varies on the ``Cookie`` and ``Authorization``
|
* the cached schema varies on the ``Cookie`` and ``Authorization`` HTTP headers to enable filtering of visible endpoints
|
||||||
HTTP headers to enable filtering of visible endpoints according to the authentication credentials of each user; note
|
according to the authentication credentials of each user; note that this means that every user accessing the schema
|
||||||
that this means that every user accessing the schema will have a separate schema cached in memory.
|
will have a separate schema cached in memory.
|
||||||
|
|
||||||
4. Validation
|
4. Validation
|
||||||
=============
|
=============
|
||||||
@@ -334,6 +334,26 @@ You can use the specification outputted by this library together with
|
|||||||
|
|
||||||
See the github page linked above for more details.
|
See the github page linked above for more details.
|
||||||
|
|
||||||
|
.. _readme-testproj:
|
||||||
|
|
||||||
|
6. Example project
|
||||||
|
==================
|
||||||
|
|
||||||
|
For additional usage examples, you can take a look at the test project in the ``testproj`` directory:
|
||||||
|
|
||||||
|
.. code:: console
|
||||||
|
|
||||||
|
$ git clone https://github.com/axnsan12/drf-yasg.git
|
||||||
|
$ cd drf-yasg
|
||||||
|
$ virtualenv venv
|
||||||
|
$ source venv/bin/activate
|
||||||
|
(venv) $ cd testproj
|
||||||
|
(venv) $ pip install -r requirements.txt
|
||||||
|
(venv) $ python manage.py migrate
|
||||||
|
(venv) $ python manage.py shell -c "import createsuperuser"
|
||||||
|
(venv) $ python manage.py runserver
|
||||||
|
(venv) $ firefox localhost:8000/swagger/
|
||||||
|
|
||||||
**********
|
**********
|
||||||
Background
|
Background
|
||||||
**********
|
**********
|
||||||
|
|||||||
@@ -3,6 +3,21 @@ Changelog
|
|||||||
#########
|
#########
|
||||||
|
|
||||||
|
|
||||||
|
*********
|
||||||
|
**1.1.3**
|
||||||
|
*********
|
||||||
|
|
||||||
|
- **FIXED:** schema view cache will now always ``Vary`` on the ``Cookie`` and ``Authentication`` (the
|
||||||
|
``Vary`` header was previously only added if ``public`` was set to ``True``) - this fixes issues related to Django
|
||||||
|
authentication in ``swagger-ui`` and ``CurrentUserDefault`` values in the schema
|
||||||
|
|
||||||
|
*********
|
||||||
|
**1.1.2**
|
||||||
|
*********
|
||||||
|
|
||||||
|
- **IMPROVED:** updated ``swagger-ui`` to version 3.8.1
|
||||||
|
- **IMPROVED:** removed some unneeded static files
|
||||||
|
|
||||||
*********
|
*********
|
||||||
**1.1.1**
|
**1.1.1**
|
||||||
*********
|
*********
|
||||||
|
|||||||
@@ -199,8 +199,6 @@ nitpick_ignore = [
|
|||||||
('py:obj', 'APIView'),
|
('py:obj', 'APIView'),
|
||||||
]
|
]
|
||||||
|
|
||||||
# TODO: inheritance aliases in sphinx 1.7
|
|
||||||
|
|
||||||
# even though the package should be already installed, the sphinx build on RTD
|
# even though the package should be already installed, the sphinx build on RTD
|
||||||
# for some reason needs the sources dir to be in the path in order for viewcode to work
|
# for some reason needs the sources dir to be in the path in order for viewcode to work
|
||||||
sys.path.insert(0, os.path.abspath('../src'))
|
sys.path.insert(0, os.path.abspath('../src'))
|
||||||
|
|||||||
@@ -58,3 +58,30 @@ See the command help for more advanced options:
|
|||||||
usage: manage.py generate_swagger [-h] [--version] [-v {0,1,2,3}]
|
usage: manage.py generate_swagger [-h] [--version] [-v {0,1,2,3}]
|
||||||
... more options ...
|
... more options ...
|
||||||
|
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
|
||||||
|
The :ref:`DEFAULT_INFO <default-swagger-settings>` setting must be defined when using the ``generate_swagger``
|
||||||
|
command. For example, the :ref:`README quickstart <readme-quickstart>` code could be modified as such:
|
||||||
|
|
||||||
|
In ``settings.py``:
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
SWAGGER_SETTINGS = {
|
||||||
|
'DEFAULT_INFO': 'import.path.to.urls.api_info',
|
||||||
|
}
|
||||||
|
|
||||||
|
In ``urls.py``:
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
api_info = openapi.Info(
|
||||||
|
title="Snippets API",
|
||||||
|
... other arguments ...
|
||||||
|
)
|
||||||
|
|
||||||
|
schema_view = get_schema_view(
|
||||||
|
# the info argument is no longer needed here as it will be picked up from DEFAULT_INFO
|
||||||
|
... other arguments ...
|
||||||
|
)
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ Paginator inspectors given to :func:`@swagger_auto_schema <.swagger_auto_schema>
|
|||||||
Swagger document attributes
|
Swagger document attributes
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
.. _default-swagger-settings:
|
||||||
|
|
||||||
DEFAULT_INFO
|
DEFAULT_INFO
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
|||||||
Generated
+3
-3
@@ -312,9 +312,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"swagger-ui-dist": {
|
"swagger-ui-dist": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.8.1.tgz",
|
||||||
"integrity": "sha1-BHfLOagE7a6Wx+COskDNWagEt3U="
|
"integrity": "sha1-jzVrkwjZl3oJ1eQYGvdCAHPtzdk="
|
||||||
},
|
},
|
||||||
"tiny-emitter": {
|
"tiny-emitter": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
|
|||||||
+1
-1
@@ -2,6 +2,6 @@
|
|||||||
"name": "drf-yasg",
|
"name": "drf-yasg",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"redoc": "^1.19.3",
|
"redoc": "^1.19.3",
|
||||||
"swagger-ui-dist": "^3.8.0"
|
"swagger-ui-dist": "^3.8.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,5 +7,4 @@ isort>=4.2
|
|||||||
flake8>=3.5.0
|
flake8>=3.5.0
|
||||||
flake8-isort>=2.3
|
flake8-isort>=2.3
|
||||||
|
|
||||||
# do not unpin this (see setup.py)
|
-r setup.txt
|
||||||
setuptools_scm==1.15.6
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# requirements for building the distributable package
|
||||||
|
|
||||||
|
# do not unpin this (see setup.py)
|
||||||
|
setuptools_scm==1.15.6
|
||||||
@@ -6,10 +6,4 @@ pytest-cov>=2.5.1
|
|||||||
git+https://github.com/pytest-dev/pytest-django.git@94cccb956435dd7a719606744ee7608397e1eafb
|
git+https://github.com/pytest-dev/pytest-django.git@94cccb956435dd7a719606744ee7608397e1eafb
|
||||||
datadiff==2.0.0
|
datadiff==2.0.0
|
||||||
|
|
||||||
# test project requirements
|
-r testproj.txt
|
||||||
Pillow>=4.3.0
|
|
||||||
pygments>=2.2.0
|
|
||||||
django-cors-headers>=2.1.0
|
|
||||||
django-filter>=1.1.0,<2.0; python_version == "2.7"
|
|
||||||
django-filter>=1.1.0; python_version >= "3.4"
|
|
||||||
djangorestframework-camel-case>=0.2.0
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# test project requirements
|
||||||
|
Pillow>=4.3.0
|
||||||
|
pygments>=2.2.0
|
||||||
|
django-cors-headers>=2.1.0
|
||||||
|
django-filter>=1.1.0,<2.0; python_version == "2.7"
|
||||||
|
django-filter>=1.1.0; python_version >= "3.4"
|
||||||
|
djangorestframework-camel-case>=0.2.0
|
||||||
@@ -6,7 +6,18 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
requirements_setup = ['setuptools_scm==1.15.6']
|
|
||||||
|
def read_req(req_file):
|
||||||
|
with open(os.path.join('requirements', req_file)) as req:
|
||||||
|
return [line for line in req.readlines() if line and not line.isspace()]
|
||||||
|
|
||||||
|
|
||||||
|
with io.open('README.rst', encoding='utf-8') as readme:
|
||||||
|
description = readme.read()
|
||||||
|
|
||||||
|
requirements = ['djangorestframework>=3.7.0'] + read_req('base.txt')
|
||||||
|
requirements_setup = read_req('setup.txt')
|
||||||
|
requirements_validation = read_req('validation.txt')
|
||||||
|
|
||||||
|
|
||||||
def _install_setup_requires(attrs):
|
def _install_setup_requires(attrs):
|
||||||
@@ -40,18 +51,6 @@ if 'sdist' in sys.argv:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def read_req(req_file):
|
|
||||||
with open(os.path.join('requirements', req_file)) as req:
|
|
||||||
return [line for line in req.readlines() if line and not line.isspace()]
|
|
||||||
|
|
||||||
|
|
||||||
with io.open('README.rst', encoding='utf-8') as readme:
|
|
||||||
description = readme.read()
|
|
||||||
|
|
||||||
requirements = ['djangorestframework>=3.7.0'] + read_req('base.txt')
|
|
||||||
requirements_validation = read_req('validation.txt')
|
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='drf-yasg',
|
name='drf-yasg',
|
||||||
use_scm_version=True,
|
use_scm_version=True,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import logging
|
|||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.utils import encoders, json
|
from rest_framework.utils import encoders, json
|
||||||
from rest_framework.viewsets import GenericViewSet
|
|
||||||
|
|
||||||
from .. import openapi
|
from .. import openapi
|
||||||
from ..utils import is_list_view
|
from ..utils import is_list_view
|
||||||
@@ -182,7 +181,7 @@ class FieldInspector(BaseInspector):
|
|||||||
|
|
||||||
- arguments specified by the ``kwargs`` parameter of :meth:`._get_partial_types`
|
- arguments specified by the ``kwargs`` parameter of :meth:`._get_partial_types`
|
||||||
- ``instance_kwargs`` passed to the constructor function
|
- ``instance_kwargs`` passed to the constructor function
|
||||||
- ``title``, ``description``, ``required``, ``default`` and ``read_only`` inferred from the field,
|
- ``title``, ``description``, ``required`` and ``default`` inferred from the field,
|
||||||
where appropriate
|
where appropriate
|
||||||
|
|
||||||
If ``existing_object`` is not ``None``, it is updated instead of creating a new object.
|
If ``existing_object`` is not ``None``, it is updated instead of creating a new object.
|
||||||
@@ -233,11 +232,6 @@ class FieldInspector(BaseInspector):
|
|||||||
if default is not None:
|
if default is not None:
|
||||||
instance_kwargs['default'] = default
|
instance_kwargs['default'] = default
|
||||||
|
|
||||||
if 'read_only' not in instance_kwargs and swagger_object_type == openapi.Schema:
|
|
||||||
# TODO: read_only is only relevant for schema `properties` - should not be generated in other cases
|
|
||||||
if field.read_only:
|
|
||||||
instance_kwargs['read_only'] = True
|
|
||||||
|
|
||||||
instance_kwargs.setdefault('title', title)
|
instance_kwargs.setdefault('title', title)
|
||||||
instance_kwargs.setdefault('description', description)
|
instance_kwargs.setdefault('description', description)
|
||||||
instance_kwargs.update(kwargs)
|
instance_kwargs.update(kwargs)
|
||||||
@@ -327,9 +321,6 @@ class ViewInspector(BaseInspector):
|
|||||||
if self.method.lower() not in ["get", "delete"]:
|
if self.method.lower() not in ["get", "delete"]:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not isinstance(self.view, GenericViewSet):
|
|
||||||
return True
|
|
||||||
|
|
||||||
return is_list_view(self.path, self.method, self.view)
|
return is_list_view(self.path, self.method, self.view)
|
||||||
|
|
||||||
def get_filter_parameters(self):
|
def get_filter_parameters(self):
|
||||||
@@ -351,10 +342,7 @@ class ViewInspector(BaseInspector):
|
|||||||
|
|
||||||
:rtype: bool
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
if not hasattr(self.view, 'paginator'):
|
if not getattr(self.view, 'paginator', None):
|
||||||
return False
|
|
||||||
|
|
||||||
if self.view.paginator is None:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.method.lower() != 'get':
|
if self.method.lower() != 'get':
|
||||||
|
|||||||
@@ -63,11 +63,18 @@ class InlineSerializerInspector(SerializerInspector):
|
|||||||
def make_schema_definition():
|
def make_schema_definition():
|
||||||
properties = OrderedDict()
|
properties = OrderedDict()
|
||||||
required = []
|
required = []
|
||||||
for key, value in serializer.fields.items():
|
for property_name, child in serializer.fields.items():
|
||||||
key = self.get_property_name(key)
|
property_name = self.get_property_name(property_name)
|
||||||
properties[key] = self.probe_field_inspectors(value, ChildSwaggerType, use_references)
|
prop_kwargs = {
|
||||||
if value.required:
|
'read_only': child.read_only or None
|
||||||
required.append(key)
|
}
|
||||||
|
prop_kwargs = filter_none(prop_kwargs)
|
||||||
|
|
||||||
|
properties[property_name] = self.probe_field_inspectors(
|
||||||
|
child, ChildSwaggerType, use_references, **prop_kwargs
|
||||||
|
)
|
||||||
|
if child.required:
|
||||||
|
required.append(property_name)
|
||||||
|
|
||||||
return SwaggerType(
|
return SwaggerType(
|
||||||
type=openapi.TYPE_OBJECT,
|
type=openapi.TYPE_OBJECT,
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
# Swagger UI Dist
|
|
||||||
[](http://badge.fury.io/js/swagger-ui-dist)
|
|
||||||
|
|
||||||
# API
|
|
||||||
|
|
||||||
This module, `swagger-ui-dist`, exposes Swagger-UI's entire dist folder as a dependency-free npm module.
|
|
||||||
Use `swagger-ui` instead, if you'd like to have npm install dependencies for you.
|
|
||||||
|
|
||||||
`SwaggerUIBundle` and `SwaggerUIStandalonePreset` can be imported:
|
|
||||||
```javascript
|
|
||||||
import { SwaggerUIBundle, SwaggerUIStandalonePreset } from "swagger-ui-dist"
|
|
||||||
```
|
|
||||||
|
|
||||||
To get an absolute path to this directory for static file serving, use the exported `getAbsoluteFSPath` method:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const swaggerUiAssetPath = require("swagger-ui-dist").getAbsoluteFSPath()
|
|
||||||
|
|
||||||
// then instantiate server that serves files from the swaggerUiAssetPath
|
|
||||||
```
|
|
||||||
|
|
||||||
For anything else, check the [Swagger-UI](https://github.com/swagger-api/swagger-ui) repository.
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
<!-- HTML for static distribution bundle build -->
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Swagger UI</title>
|
|
||||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
|
|
||||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
|
|
||||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
|
||||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
|
||||||
<style>
|
|
||||||
html
|
|
||||||
{
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow: -moz-scrollbars-vertical;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
*,
|
|
||||||
*:before,
|
|
||||||
*:after
|
|
||||||
{
|
|
||||||
box-sizing: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin:0;
|
|
||||||
background: #fafafa;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0">
|
|
||||||
<defs>
|
|
||||||
<symbol viewBox="0 0 20 20" id="unlocked">
|
|
||||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
|
|
||||||
</symbol>
|
|
||||||
|
|
||||||
<symbol viewBox="0 0 20 20" id="locked">
|
|
||||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/>
|
|
||||||
</symbol>
|
|
||||||
|
|
||||||
<symbol viewBox="0 0 20 20" id="close">
|
|
||||||
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/>
|
|
||||||
</symbol>
|
|
||||||
|
|
||||||
<symbol viewBox="0 0 20 20" id="large-arrow">
|
|
||||||
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/>
|
|
||||||
</symbol>
|
|
||||||
|
|
||||||
<symbol viewBox="0 0 20 20" id="large-arrow-down">
|
|
||||||
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/>
|
|
||||||
</symbol>
|
|
||||||
|
|
||||||
|
|
||||||
<symbol viewBox="0 0 24 24" id="jump-to">
|
|
||||||
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/>
|
|
||||||
</symbol>
|
|
||||||
|
|
||||||
<symbol viewBox="0 0 24 24" id="expand">
|
|
||||||
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
|
|
||||||
</symbol>
|
|
||||||
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
<div id="swagger-ui"></div>
|
|
||||||
|
|
||||||
<script src="./swagger-ui-bundle.js"> </script>
|
|
||||||
<script src="./swagger-ui-standalone-preset.js"> </script>
|
|
||||||
<script>
|
|
||||||
window.onload = function() {
|
|
||||||
|
|
||||||
// Build a system
|
|
||||||
const ui = SwaggerUIBundle({
|
|
||||||
url: "http://petstore.swagger.io/v2/swagger.json",
|
|
||||||
dom_id: '#swagger-ui',
|
|
||||||
deepLinking: true,
|
|
||||||
presets: [
|
|
||||||
SwaggerUIBundle.presets.apis,
|
|
||||||
SwaggerUIStandalonePreset
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
SwaggerUIBundle.plugins.DownloadUrl
|
|
||||||
],
|
|
||||||
layout: "StandaloneLayout"
|
|
||||||
})
|
|
||||||
|
|
||||||
window.ui = ui
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
{"version":3,"sources":[],"names":[],"mappings":"","file":"swagger-ui.css","sourceRoot":""}
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+25
-19
@@ -4,6 +4,7 @@ from collections import OrderedDict
|
|||||||
|
|
||||||
from rest_framework import serializers, status
|
from rest_framework import serializers, status
|
||||||
from rest_framework.mixins import DestroyModelMixin, RetrieveModelMixin, UpdateModelMixin
|
from rest_framework.mixins import DestroyModelMixin, RetrieveModelMixin, UpdateModelMixin
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -85,6 +86,7 @@ def swagger_auto_schema(method=None, methods=None, auto_schema=None, request_bod
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(view_method):
|
def decorator(view_method):
|
||||||
|
assert not any(hm in extra_overrides for hm in APIView.http_method_names), "HTTP method names not allowed here"
|
||||||
data = {
|
data = {
|
||||||
'auto_schema': auto_schema,
|
'auto_schema': auto_schema,
|
||||||
'request_body': request_body,
|
'request_body': request_body,
|
||||||
@@ -97,30 +99,23 @@ def swagger_auto_schema(method=None, methods=None, auto_schema=None, request_bod
|
|||||||
'paginator_inspectors': list(paginator_inspectors) if paginator_inspectors else None,
|
'paginator_inspectors': list(paginator_inspectors) if paginator_inspectors else None,
|
||||||
'field_inspectors': list(field_inspectors) if field_inspectors else None,
|
'field_inspectors': list(field_inspectors) if field_inspectors else None,
|
||||||
}
|
}
|
||||||
data = {k: v for k, v in data.items() if v is not None}
|
data = filter_none(data)
|
||||||
data.update(extra_overrides)
|
data.update(extra_overrides)
|
||||||
|
if not data: # pragma: no cover
|
||||||
|
# no overrides to set, no use in doing more work
|
||||||
|
return
|
||||||
|
|
||||||
# if the method is a detail_route or list_route, it will have a bind_to_methods attribute
|
# if the method is a detail_route or list_route, it will have a bind_to_methods attribute
|
||||||
bind_to_methods = getattr(view_method, 'bind_to_methods', [])
|
bind_to_methods = getattr(view_method, 'bind_to_methods', [])
|
||||||
# if the method is actually a function based view (@api_view), it will have a 'cls' attribute
|
# if the method is actually a function based view (@api_view), it will have a 'cls' attribute
|
||||||
view_cls = getattr(view_method, 'cls', None)
|
view_cls = getattr(view_method, 'cls', None)
|
||||||
http_method_names = getattr(view_cls, 'http_method_names', [])
|
http_method_names = getattr(view_cls, 'http_method_names', [])
|
||||||
if bind_to_methods or http_method_names:
|
|
||||||
# detail_route, list_route or api_view
|
|
||||||
assert bool(http_method_names) != bool(bind_to_methods), "this should never happen"
|
|
||||||
available_methods = http_method_names + bind_to_methods
|
available_methods = http_method_names + bind_to_methods
|
||||||
existing_data = getattr(view_method, '_swagger_auto_schema', {})
|
existing_data = getattr(view_method, '_swagger_auto_schema', {})
|
||||||
|
|
||||||
if http_method_names:
|
|
||||||
_route = "api_view"
|
|
||||||
else:
|
|
||||||
_route = "detail_route" if view_method.detail else "list_route"
|
|
||||||
|
|
||||||
_methods = methods
|
_methods = methods
|
||||||
if len(available_methods) > 1:
|
if methods or method:
|
||||||
assert methods or method, \
|
|
||||||
"on multi-method %s, you must specify swagger_auto_schema on a per-method basis " \
|
|
||||||
"using one of the `method` or `methods` arguments" % _route
|
|
||||||
assert bool(methods) != bool(method), "specify either method or methods"
|
assert bool(methods) != bool(method), "specify either method or methods"
|
||||||
assert not isinstance(methods, str), "`methods` expects to receive a list of methods;" \
|
assert not isinstance(methods, str), "`methods` expects to receive a list of methods;" \
|
||||||
" use `method` for a single argument"
|
" use `method` for a single argument"
|
||||||
@@ -128,17 +123,28 @@ def swagger_auto_schema(method=None, methods=None, auto_schema=None, request_bod
|
|||||||
_methods = [method.lower()]
|
_methods = [method.lower()]
|
||||||
else:
|
else:
|
||||||
_methods = [mth.lower() for mth in methods]
|
_methods = [mth.lower() for mth in methods]
|
||||||
assert not any(mth in existing_data for mth in _methods), "method defined multiple times"
|
assert all(mth in available_methods for mth in _methods), "http method not bound to view"
|
||||||
assert all(mth in available_methods for mth in _methods), "method not bound to %s" % _route
|
assert not any(mth in existing_data for mth in _methods), "http method defined multiple times"
|
||||||
|
|
||||||
|
if available_methods:
|
||||||
|
# detail_route, list_route or api_view
|
||||||
|
assert bool(http_method_names) != bool(bind_to_methods), "this should never happen"
|
||||||
|
|
||||||
|
if len(available_methods) > 1:
|
||||||
|
assert _methods, \
|
||||||
|
"on multi-method api_view, detail_route or list_route, you must specify swagger_auto_schema on " \
|
||||||
|
"a per-method basis using one of the `method` or `methods` arguments"
|
||||||
|
else:
|
||||||
|
# for a single-method view we assume that single method as the decorator target
|
||||||
|
_methods = _methods or available_methods
|
||||||
|
|
||||||
existing_data.update((mth.lower(), data) for mth in _methods)
|
existing_data.update((mth.lower(), data) for mth in _methods)
|
||||||
else:
|
|
||||||
existing_data[available_methods[0]] = data
|
|
||||||
view_method._swagger_auto_schema = existing_data
|
view_method._swagger_auto_schema = existing_data
|
||||||
else:
|
else:
|
||||||
assert method is None and methods is None, \
|
assert not _methods, \
|
||||||
"the methods argument should only be specified when decorating a detail_route or list_route; you " \
|
"the methods argument should only be specified when decorating a detail_route or list_route; you " \
|
||||||
"should also ensure that you put the swagger_auto_schema decorator AFTER (above) the _route decorator"
|
"should also ensure that you put the swagger_auto_schema decorator AFTER (above) the _route decorator"
|
||||||
|
assert not existing_data, "a single view method should only be decorated once"
|
||||||
view_method._swagger_auto_schema = data
|
view_method._swagger_auto_schema = data
|
||||||
|
|
||||||
return view_method
|
return view_method
|
||||||
@@ -166,7 +172,7 @@ def is_list_view(path, method, view):
|
|||||||
# a detail_route is surely not a list route
|
# a detail_route is surely not a list route
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# for APIView, if it's a detail view it can't also be a list view
|
# for GenericAPIView, if it's a detail view it can't also be a list view
|
||||||
if isinstance(view, (RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin)):
|
if isinstance(view, (RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin)):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ def get_schema_view(info=None, url=None, patterns=None, urlconf=None, public=Fal
|
|||||||
|
|
||||||
Arguments described in :meth:`.as_cached_view`.
|
Arguments described in :meth:`.as_cached_view`.
|
||||||
"""
|
"""
|
||||||
if not cls.public:
|
|
||||||
view = vary_on_headers('Cookie', 'Authorization')(view)
|
view = vary_on_headers('Cookie', 'Authorization')(view)
|
||||||
view = cache_page(cache_timeout, **cache_kwargs)(view)
|
view = cache_page(cache_timeout, **cache_kwargs)(view)
|
||||||
view = deferred_never_cache(view) # disable in-browser caching
|
view = deferred_never_cache(view) # disable in-browser caching
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
User.objects.filter(username='admin').delete()
|
username = 'admin'
|
||||||
User.objects.create_superuser('admin', 'admin@admin.admin', 'passwordadmin')
|
email = 'admin@admin.admin'
|
||||||
|
password = 'passwordadmin'
|
||||||
|
User.objects.filter(username=username).delete()
|
||||||
|
User.objects.create_superuser(username, email, password)
|
||||||
|
|
||||||
|
print("Created superuser '%s <%s>' with password '%s'" % (username, email, password))
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
drf-yasg[validation]
|
||||||
|
Django>=1.11.7
|
||||||
|
-r ../requirements/testproj.txt
|
||||||
@@ -1110,7 +1110,6 @@ definitions:
|
|||||||
format: slug
|
format: slug
|
||||||
pattern: ^[-a-zA-Z0-9_]+$
|
pattern: ^[-a-zA-Z0-9_]+$
|
||||||
readOnly: true
|
readOnly: true
|
||||||
readOnly: true
|
|
||||||
uniqueItems: true
|
uniqueItems: true
|
||||||
securityDefinitions:
|
securityDefinitions:
|
||||||
basic:
|
basic:
|
||||||
|
|||||||
@@ -52,10 +52,7 @@ def test_caching(client, validate_schema):
|
|||||||
prev_schema = None
|
prev_schema = None
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
_validate_ui_schema_view(client, '/cached/redoc/', 'redoc/redoc.min.js')
|
_validate_text_schema_view(client, validate_schema, '/cached/swagger.yaml', yaml_sane_load)
|
||||||
_validate_text_schema_view(client, validate_schema, '/cached/redoc/?format=openapi', json.loads)
|
|
||||||
_validate_ui_schema_view(client, '/cached/swagger/', 'swagger-ui-dist/swagger-ui-bundle.js')
|
|
||||||
_validate_text_schema_view(client, validate_schema, '/cached/swagger/?format=openapi', json.loads)
|
|
||||||
|
|
||||||
json_schema = client.get('/cached/swagger.json')
|
json_schema = client.get('/cached/swagger.json')
|
||||||
assert json_schema.status_code == 200
|
assert json_schema.status_code == 200
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ max-line-length = 120
|
|||||||
exclude = **/migrations/*
|
exclude = **/migrations/*
|
||||||
|
|
||||||
[isort]
|
[isort]
|
||||||
skip = .eggs,.tox,docs
|
skip = .eggs,.tox,docs,env,venv
|
||||||
skip_glob = **/migrations/*
|
skip_glob = **/migrations/*
|
||||||
not_skip = __init__.py
|
not_skip = __init__.py
|
||||||
atomic = true
|
atomic = true
|
||||||
|
|||||||
+5
-3
@@ -1,7 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -ev
|
||||||
|
|
||||||
npm update
|
npm update
|
||||||
cp node_modules/redoc/dist/redoc.min.js src/drf_yasg/static/drf-yasg/redoc/redoc.min.js
|
cp node_modules/redoc/dist/redoc.min.js src/drf_yasg/static/drf-yasg/redoc/redoc.min.js
|
||||||
cp -r node_modules/swagger-ui-dist src/drf_yasg/static/drf-yasg/
|
cp -r node_modules/swagger-ui-dist src/drf_yasg/static/drf-yasg/
|
||||||
rm -f src/drf_yasg/static/drf-yasg/swagger-ui-dist/package.json src/drf_yasg/static/drf-yasg/swagger-ui-dist/.npmignore
|
pushd src/drf_yasg/static/drf-yasg/swagger-ui-dist/ >/dev/null
|
||||||
|
rm -f package.json .npmignore README.md
|
||||||
|
rm -f index.html *.map
|
||||||
|
popd >/dev/null
|
||||||
|
|||||||
Reference in New Issue
Block a user