Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1fe8c2c03c | |||
| b8512bda8e | |||
| 2bc9addc99 | |||
| 6df2362156 | |||
| e5a569ebf7 | |||
| 470c993b98 | |||
| a5e4386f38 | |||
| 6bd91faa5d | |||
| 667c9c1002 | |||
| 8b0da2607f |
+9
-2
@@ -11,10 +11,17 @@ Generate **real** Swagger/OpenAPI 2.0 specifications from a Django Rest Framewor
|
||||
|
||||
Compatible with
|
||||
|
||||
- **Django Rest Framework**: 3.7.7, 3.8
|
||||
- **Django Rest Framework**: 3.7.7, 3.8, 3.9
|
||||
- **Django**: 1.11, 2.0, 2.1
|
||||
- **Python**: 2.7, 3.4, 3.5, 3.6, 3.7
|
||||
|
||||
Only the latest patch version of each ``major.minor`` series of Python, Django and Django REST Framework is supported.
|
||||
|
||||
**Only the latest version of drf-yasg is supported.** Support of old versions is dropped immediately with the release
|
||||
of a new version. Please do not create issues before upgrading to the latest release available at the time. Regression
|
||||
reports are accepted and will be resolved with a new release as quickly as possible. Removed features will usually go
|
||||
through a deprecation cycle of a few minor releases.
|
||||
|
||||
Resources:
|
||||
|
||||
* **Source**: https://github.com/axnsan12/drf-yasg/
|
||||
@@ -204,7 +211,7 @@ caching the schema view in-memory, with some sane defaults:
|
||||
4. Validation
|
||||
=============
|
||||
|
||||
Given the numerous methods to manually customzie the generated schema, it makes sense to validate the result to ensure
|
||||
Given the numerous methods to manually customize 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 :python:`validators=['flex', 'ssv']` to ``get_schema_view``; if the generated
|
||||
schema is not valid, a :python:`SwaggerValidationError` is raised by the handling codec.
|
||||
|
||||
+12
-1
@@ -2,6 +2,17 @@
|
||||
Changelog
|
||||
#########
|
||||
|
||||
|
||||
**********
|
||||
**1.12.1**
|
||||
**********
|
||||
|
||||
*Release date: Dec 28, 2018*
|
||||
|
||||
- **IMPROVED:** updated ``ReDoc`` to version 2.0.0-rc.0
|
||||
- **FIXED:** management command will now correctly fall back to ``DEFAULT_VERSION`` for mock request
|
||||
- **FIXED:** fixed bad "raised exception during schema generation" warnings caused by missing ``self`` parameter
|
||||
|
||||
**********
|
||||
**1.12.0**
|
||||
**********
|
||||
@@ -30,7 +41,7 @@ Changelog
|
||||
Starting with this version, the ``setup_requires`` argument was dropped from ``setup.py`` in favor of
|
||||
``build-system.requires`` in ``pyproject.toml`` . This means that for correctly building or installing from sdist,
|
||||
you will need to use a PEP517/PEP518 compliant tool (tox>=3.3.0, setuptools>=40, pip>=10.0, pep517.build) or manually
|
||||
install the build requirements yourself (just ```setuptools`` and ``setuptools-scm``, for now).
|
||||
install the build requirements yourself (just ``setuptools`` and ``setuptools-scm``, for now).
|
||||
|
||||
Additionally, for correct package version detection, a full git checkout is required when building (this was always the
|
||||
case). Building without ``.git`` or without ``setuptools-scm`` will result in a distribution with a version like
|
||||
|
||||
Generated
+78
-32
@@ -4,9 +4,9 @@
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.1.5.tgz",
|
||||
"integrity": "sha512-xKnPpXG/pvK1B90JkwwxSGii90rQGKtzcMt2gI5G6+M0REXaq6rOHsGC2ay6/d0Uje7zzvSzjEzfR3ENhFlrfA==",
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.2.0.tgz",
|
||||
"integrity": "sha512-oouEibCbHMVdZSDlJBO6bZmID/zA/G/Qx3H1d3rSNPTD+L8UNKvCat7aKWSJ74zYbm5zWGh0GQN0hKj8zYFTCg==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.12.0"
|
||||
}
|
||||
@@ -19,6 +19,11 @@
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"big.js": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
|
||||
"integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="
|
||||
},
|
||||
"call-me-maybe": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz",
|
||||
@@ -61,6 +66,11 @@
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-1.0.8.tgz",
|
||||
"integrity": "sha512-vetRFbN1SXSPfP3ClIiYnxTrXquSqakBEOoB5JESn0SVcSYzpu6ougjakpKnskGctYdlNpwf+riUHSkG7d4XUw=="
|
||||
},
|
||||
"emojis-list": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
|
||||
"integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k="
|
||||
},
|
||||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
@@ -105,9 +115,9 @@
|
||||
}
|
||||
},
|
||||
"hoist-non-react-statics": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.2.0.tgz",
|
||||
"integrity": "sha512-3IascCRfaEkbmHjJnUxWSspIUE1okLPjGTMVXW8zraUo1t3yg1BadKAxAGILHwgoBzmMnzrgeeaDGBvpuPz6dA==",
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.2.1.tgz",
|
||||
"integrity": "sha512-TFsu3TV3YLY+zFTZDrN8L2DTFanObwmBLpWvJs1qfUuEQ5bTAdFcwfx2T/bsCXfM9QHSLvjfP+nihEl0yvozxw==",
|
||||
"requires": {
|
||||
"react-is": "^16.3.2"
|
||||
}
|
||||
@@ -144,6 +154,29 @@
|
||||
"ono": "^4.0.10"
|
||||
}
|
||||
},
|
||||
"json5": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "http://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
|
||||
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
|
||||
"requires": {
|
||||
"minimist": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.0.tgz",
|
||||
"integrity": "sha512-KkQxP+pVgJC6ypy8ePypyhsV/hZeyVlkqiqrxe4pDgCwClbzmr3dGy8LbeSVhmfzYmCpOovdrVs/9chsQXCrLQ==",
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^2.0.0",
|
||||
"json5": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"lodash.merge": {
|
||||
"version": "4.6.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz",
|
||||
"integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ=="
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
@@ -179,10 +212,15 @@
|
||||
"dom-walk": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
||||
},
|
||||
"mobx-react": {
|
||||
"version": "5.4.2",
|
||||
"resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-5.4.2.tgz",
|
||||
"integrity": "sha512-alSN0KDAAOb1OkYujfoJjjk0JWxWRKO4sLGB4hN2CuvaJMrlj7bhGQe7CBMJvEFNjtJRbhJcquYVjQ3rrH2zQQ==",
|
||||
"version": "5.4.3",
|
||||
"resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-5.4.3.tgz",
|
||||
"integrity": "sha512-WC8yFlwvJ91hy8j6CrydAuFteUafcuvdITFQeHl3LRIf5ayfT/4W3M/byhEYD2BcJWejeXr8y4Rh2H26RunCRQ==",
|
||||
"requires": {
|
||||
"hoist-non-react-statics": "^3.0.0",
|
||||
"react-lifecycles-compat": "^3.0.2"
|
||||
@@ -194,9 +232,9 @@
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||
},
|
||||
"ono": {
|
||||
"version": "4.0.10",
|
||||
"resolved": "https://registry.npmjs.org/ono/-/ono-4.0.10.tgz",
|
||||
"integrity": "sha512-4Xz4hlbq7MzV0I3vKfZwRvyj8tCbXODqBNzFqtkjP+KTV93zzDRju8kw1qnf6P5kcZ2+xlIq6wSCqA+euSKxhA==",
|
||||
"version": "4.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ono/-/ono-4.0.11.tgz",
|
||||
"integrity": "sha512-jQ31cORBFE6td25deYeD80wxKBMj+zBmHTrVxnc6CKhx8gho6ipmWM5zj/oeoqioZ99yqBls9Z/9Nss7J26G2g==",
|
||||
"requires": {
|
||||
"format-util": "^1.0.3"
|
||||
}
|
||||
@@ -215,9 +253,9 @@
|
||||
"integrity": "sha512-/2Sk/khljhdrsamjJYS5NjrH+GKEHEwh7zFSiYyxROyYKagkE4kSn2zDQDRTOMo8mpT2jikxx6yI1dG7lNP/hw=="
|
||||
},
|
||||
"polished": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/polished/-/polished-2.3.0.tgz",
|
||||
"integrity": "sha512-G2yD9LhJy5HBuU+Im5qe70ubaJI/ZTTOIJO6GRMwJ2WSoAiPzlm8+LjAXMnm9/K0E0NumRVHvQu2HHPKQSYQjw==",
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/polished/-/polished-2.3.1.tgz",
|
||||
"integrity": "sha512-0mGyvVrHVRN92wfohriBWmMF4JLEnGgpZbpwPrNDhpB8NrX6lYI8GGWXEfrmrF+ZXg52Jkwd+D0rxViOvXM9RQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.0.0"
|
||||
}
|
||||
@@ -245,24 +283,27 @@
|
||||
}
|
||||
},
|
||||
"react-dropdown": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/react-dropdown/-/react-dropdown-1.6.2.tgz",
|
||||
"integrity": "sha512-6RpKAFEVZLr53y91qnxC9rAWcoDvq8A9YstmeSV2AQgJxNFRcsreN1mJNRUctSvIwm0Hph07ouMvDc2GvfQBsA==",
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/react-dropdown/-/react-dropdown-1.6.3.tgz",
|
||||
"integrity": "sha512-UAcVCsxeIkn5N7xpHr+WHDPbtUO+LsJyGiUT5PsdkVVPDJp9e42oxGICDyjcQ5rWa7DS0ctmn770JcM4gIvTiQ==",
|
||||
"requires": {
|
||||
"classnames": "^2.2.3"
|
||||
}
|
||||
},
|
||||
"react-hot-loader": {
|
||||
"version": "4.3.12",
|
||||
"resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-4.3.12.tgz",
|
||||
"integrity": "sha512-GMM4TsqUVss2QPe+Y33NlgydA5/+7tAVQxR0rZqWvBpapM8JhD7p6ymMwSZzr5yxjoXXlK/6P6qNQBOqm1dqdg==",
|
||||
"version": "4.6.3",
|
||||
"resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-4.6.3.tgz",
|
||||
"integrity": "sha512-FUvRO8dwbeLnc3mgLn8ARuSh8NnLBYJyiRjFn+grY/5GupSyPqv0U7ixgwXro77hwDplhm8z9wU7FlJ8kZqiAQ==",
|
||||
"requires": {
|
||||
"fast-levenshtein": "^2.0.6",
|
||||
"global": "^4.3.0",
|
||||
"hoist-non-react-statics": "^2.5.0",
|
||||
"loader-utils": "^1.1.0",
|
||||
"lodash.merge": "^4.6.1",
|
||||
"prop-types": "^15.6.1",
|
||||
"react-lifecycles-compat": "^3.0.4",
|
||||
"shallowequal": "^1.0.2"
|
||||
"shallowequal": "^1.0.2",
|
||||
"source-map": "^0.7.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"hoist-non-react-statics": {
|
||||
@@ -273,9 +314,9 @@
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.6.3",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.6.3.tgz",
|
||||
"integrity": "sha512-u7FDWtthB4rWibG/+mFbVd5FvdI20yde86qKGx4lVUTWmPlSWQ4QxbBIrrs+HnXGbxOUlUzTAP/VDmvCwaP2yA=="
|
||||
"version": "16.7.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.7.0.tgz",
|
||||
"integrity": "sha512-Z0VRQdF4NPDoI0tsXVMLkJLiwEBa+RP66g0xDHxgxysxSoCUccSten4RTF/UFvZF1dZvZ9Zu1sx+MDXwcOR34g=="
|
||||
},
|
||||
"react-lifecycles-compat": {
|
||||
"version": "3.0.4",
|
||||
@@ -292,9 +333,9 @@
|
||||
}
|
||||
},
|
||||
"redoc": {
|
||||
"version": "2.0.0-alpha.41",
|
||||
"resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-alpha.41.tgz",
|
||||
"integrity": "sha512-g8XnoDRRNLq2GVk8cNYKtO6cK5cPK95qdCIc6PSNo2ueBVWEQBKooriSF57B6GVuaqoOBacqlGHQDPakvBQLYA==",
|
||||
"version": "2.0.0-rc.0",
|
||||
"resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-xH0xZ0mYFgWp4aUk9TAsGUKlyiT5Ph0MvhO3rK/cKUaCUZ+vwuOANA00Sf5hOMtXnjsXgJxC7i7fJ7tyX2yxWg==",
|
||||
"requires": {
|
||||
"classnames": "^2.2.6",
|
||||
"decko": "^1.2.0",
|
||||
@@ -337,13 +378,18 @@
|
||||
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
|
||||
},
|
||||
"slugify": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/slugify/-/slugify-1.3.3.tgz",
|
||||
"integrity": "sha512-aFvcXobuowA7RqU4IBVJvqmhkREDIqsj4oIJKk6JuZ5EO1PCwtAAwDCl8TdsMs4J9zCoDAVkB9FLUElDjNcRSg=="
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/slugify/-/slugify-1.3.4.tgz",
|
||||
"integrity": "sha512-KP0ZYk5hJNBS8/eIjGkFDCzGQIoZ1mnfQRYS5WM3273z+fxGWXeN0fkwf2ebEweydv9tioZIHGZKoF21U07/nw=="
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ=="
|
||||
},
|
||||
"sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
},
|
||||
"stickyfill": {
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "drf-yasg",
|
||||
"dependencies": {
|
||||
"redoc": "^2.0.0-alpha.41",
|
||||
"redoc": "^2.0.0-rc.0",
|
||||
"swagger-ui-dist": "^3.20.4"
|
||||
},
|
||||
"repository": {
|
||||
|
||||
+23
-4
@@ -88,7 +88,7 @@ class _OpenAPICodec(object):
|
||||
|
||||
:param dict spec: a python dict
|
||||
:return: string representation of ``spec``
|
||||
:rtype: str
|
||||
:rtype: str or bytes
|
||||
"""
|
||||
raise NotImplementedError("override this method")
|
||||
|
||||
@@ -105,9 +105,22 @@ class _OpenAPICodec(object):
|
||||
class OpenAPICodecJson(_OpenAPICodec):
|
||||
media_type = 'application/json'
|
||||
|
||||
def __init__(self, validators, pretty=False, media_type='application/json'):
|
||||
super(OpenAPICodecJson, self).__init__(validators)
|
||||
self.pretty = pretty
|
||||
self.media_type = media_type
|
||||
|
||||
def _dump_dict(self, spec):
|
||||
"""Dump ``spec`` into JSON."""
|
||||
return json.dumps(spec)
|
||||
"""Dump ``spec`` into JSON.
|
||||
|
||||
:rtype: str"""
|
||||
if self.pretty:
|
||||
out = json.dumps(spec, indent=4, separators=(',', ': '))
|
||||
if out[-1] != '\n':
|
||||
out += '\n'
|
||||
return out
|
||||
else:
|
||||
return json.dumps(spec)
|
||||
|
||||
|
||||
YAML_MAP_TAG = u'tag:yaml.org,2002:map'
|
||||
@@ -201,6 +214,12 @@ def yaml_sane_load(stream):
|
||||
class OpenAPICodecYaml(_OpenAPICodec):
|
||||
media_type = 'application/yaml'
|
||||
|
||||
def __init__(self, validators, media_type='application/yaml'):
|
||||
super(OpenAPICodecYaml, self).__init__(validators)
|
||||
self.media_type = media_type
|
||||
|
||||
def _dump_dict(self, spec):
|
||||
"""Dump ``spec`` into YAML."""
|
||||
"""Dump ``spec`` into YAML.
|
||||
|
||||
:rtype: bytes"""
|
||||
return yaml_sane_dump(spec, binary=True)
|
||||
|
||||
@@ -12,21 +12,44 @@ NotHandled = object()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def is_callable_method(cls_or_instance, method_name):
|
||||
method = getattr(cls_or_instance, method_name)
|
||||
if inspect.ismethod(method) and getattr(method, '__self__', None):
|
||||
# bound classmethod or instance method
|
||||
return method, True
|
||||
|
||||
try:
|
||||
# inspect.getattr_static was added in python 3.2
|
||||
from inspect import getattr_static
|
||||
|
||||
# on python 3, both unbound instance methods (i.e. getattr(cls, mth)) and static methods are plain functions
|
||||
# getattr_static allows us to check the type of the method descriptor; for `@staticmethod` this is staticmethod
|
||||
return method, isinstance(getattr_static(cls_or_instance, method_name, None), staticmethod)
|
||||
except ImportError:
|
||||
# python 2 still has unbound methods, so ismethod <=> !staticmethod TODO: remove when dropping python 2.7
|
||||
return method, not inspect.ismethod(method)
|
||||
|
||||
|
||||
def call_view_method(view, method_name, fallback_attr=None, default=None):
|
||||
"""Call a view method which might throw an exception. If an exception is thrown, log an informative error message
|
||||
and return the value of fallback_attr, or default if not present.
|
||||
and return the value of fallback_attr, or default if not present. The method must be callable without any arguments
|
||||
except cls or self.
|
||||
|
||||
:param rest_framework.views.APIView view:
|
||||
:param view: view class or instance; if a class is passed, instance methods won't be called
|
||||
:type view: rest_framework.views.APIView or type[rest_framework.views.APIView]
|
||||
:param str method_name: name of a method on the view
|
||||
:param str fallback_attr: name of an attribute on the view to fall back on, if calling the method fails
|
||||
:param default: default value if all else fails
|
||||
:return: view method's return value, or value of view's fallback_attr, or default
|
||||
:rtype: any or None
|
||||
"""
|
||||
if hasattr(view, method_name):
|
||||
try:
|
||||
return getattr(view, method_name)()
|
||||
view_method, is_callabale = is_callable_method(view, method_name)
|
||||
if is_callabale:
|
||||
return view_method()
|
||||
except Exception: # pragma: no cover
|
||||
logger.warning("view's %s.get_parsers raised exception during schema generation; use "
|
||||
logger.warning("view's %s raised exception during schema generation; use "
|
||||
"`getattr(self, 'swagger_fake_view', False)` to detect and short-circuit this",
|
||||
type(view).__name__, exc_info=True)
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ def get_queryset_from_view(view, serializer=None):
|
||||
:return: queryset or ``None``
|
||||
"""
|
||||
try:
|
||||
queryset = call_view_method(view, 'get_queryset', 'queryset', None)
|
||||
queryset = call_view_method(view, 'get_queryset', 'queryset')
|
||||
|
||||
if queryset is not None and serializer is not None:
|
||||
# make sure the view is actually using *this* serializer
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
from importlib import import_module
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.utils.module_loading import import_string
|
||||
from rest_framework.settings import api_settings
|
||||
from rest_framework.test import APIRequestFactory, force_authenticate
|
||||
from rest_framework.views import APIView
|
||||
|
||||
@@ -15,15 +14,6 @@ from ...app_settings import swagger_settings
|
||||
from ...codecs import OpenAPICodecJson, OpenAPICodecYaml
|
||||
|
||||
|
||||
def import_class(import_string):
|
||||
if not import_string:
|
||||
return None
|
||||
|
||||
module_path, class_name = import_string.rsplit('.', 1)
|
||||
module = import_module(module_path)
|
||||
return getattr(module, class_name)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Write the Swagger schema to disk in JSON or YAML format.'
|
||||
|
||||
@@ -56,7 +46,7 @@ class Command(BaseCommand):
|
||||
parser.add_argument(
|
||||
'-m', '--mock-request', dest='mock',
|
||||
default=False, action='store_true',
|
||||
help='Use a mock request when generating the swagger schema. This is useful if your views or serializers'
|
||||
help='Use a mock request when generating the swagger schema. This is useful if your views or serializers '
|
||||
'depend on context from a request in order to function.'
|
||||
)
|
||||
parser.add_argument(
|
||||
@@ -85,11 +75,9 @@ class Command(BaseCommand):
|
||||
|
||||
def write_schema(self, schema, stream, format):
|
||||
if format == 'json':
|
||||
codec = OpenAPICodecJson(validators=[])
|
||||
swagger_json = codec.encode(schema)
|
||||
swagger_json = json.loads(swagger_json.decode('utf-8'), object_pairs_hook=OrderedDict)
|
||||
pretty_json = json.dumps(swagger_json, indent=4, ensure_ascii=True)
|
||||
stream.write(pretty_json)
|
||||
codec = OpenAPICodecJson(validators=[], pretty=True)
|
||||
swagger_json = codec.encode(schema).decode('utf-8')
|
||||
stream.write(swagger_json)
|
||||
elif format == 'yaml':
|
||||
codec = OpenAPICodecYaml(validators=[])
|
||||
swagger_yaml = codec.encode(schema).decode('utf-8')
|
||||
@@ -107,6 +95,20 @@ class Command(BaseCommand):
|
||||
request = APIView().initialize_request(request)
|
||||
return request
|
||||
|
||||
def get_schema_generator(self, generator_class_name, api_info, api_version, api_url):
|
||||
generator_class = swagger_settings.DEFAULT_GENERATOR_CLASS
|
||||
if generator_class_name:
|
||||
generator_class = import_string(generator_class_name)
|
||||
|
||||
return generator_class(
|
||||
info=api_info,
|
||||
version=api_version,
|
||||
url=api_url,
|
||||
)
|
||||
|
||||
def get_schema(self, generator, request, public):
|
||||
return generator.get_schema(request=request, public=public)
|
||||
|
||||
def handle(self, output_file, overwrite, format, api_url, mock, api_version, user, private, generator_class_name,
|
||||
*args, **kwargs):
|
||||
# disable logs of WARNING and below
|
||||
@@ -142,16 +144,12 @@ class Command(BaseCommand):
|
||||
if mock:
|
||||
request = self.get_mock_request(api_url, format, user)
|
||||
|
||||
api_version = api_version or api_settings.DEFAULT_VERSION
|
||||
if request and api_version:
|
||||
request.version = api_version
|
||||
|
||||
generator_class = import_class(generator_class_name) or swagger_settings.DEFAULT_GENERATOR_CLASS
|
||||
generator = generator_class(
|
||||
info=info,
|
||||
version=api_version,
|
||||
url=api_url,
|
||||
)
|
||||
schema = generator.get_schema(request=request, public=not private)
|
||||
generator = self.get_schema_generator(generator_class_name, info, api_version, api_url)
|
||||
schema = self.get_schema(generator, request, not private)
|
||||
|
||||
if output_file == '-':
|
||||
self.write_schema(schema, self.stdout, format)
|
||||
|
||||
+19
-19
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user