Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 05901e99aa | |||
| a211184478 | |||
| a3e81ef7f6 |
+11
-2
@@ -2,12 +2,21 @@
|
|||||||
Changelog
|
Changelog
|
||||||
#########
|
#########
|
||||||
|
|
||||||
|
*********
|
||||||
|
**1.3.1**
|
||||||
|
*********
|
||||||
|
|
||||||
|
- **FIXED:** fixed a bug that would sometimes cause endpoints to wrongly be output as form operations (:issue:`50`)
|
||||||
|
- **IMPROVED:** added generation of ``produces`` based on renderer classes
|
||||||
|
- **IMPROVED:** added generation of top-level ``consumes`` and ``produces`` based on
|
||||||
|
``DEFAULT_PARSER_CLASSES`` and ``DEFAULT_RENDERER_CLASSES`` (:issue:`48`)
|
||||||
|
|
||||||
*********
|
*********
|
||||||
**1.3.0**
|
**1.3.0**
|
||||||
*********
|
*********
|
||||||
|
|
||||||
- **ADDED:** security requirements are now correctly set and can be customized; this should fix
|
- **ADDED:** security requirements are now correctly set and can be customized; this should fix problems related
|
||||||
problems related to authentication in ``swagger-ui`` Try it out! (:issue:`50`, :pr:`54`)
|
to authentication in ``swagger-ui`` Try it out! (:issue:`50`, :pr:`54`)
|
||||||
- **IMPROVED:** updated ``swagger-ui`` to version 3.9.2
|
- **IMPROVED:** updated ``swagger-ui`` to version 3.9.2
|
||||||
- **IMPROVED:** updated ``ReDoc`` to version 1.20.0
|
- **IMPROVED:** updated ``ReDoc`` to version 1.20.0
|
||||||
- **FIXED:** fixed an exception caused by a warning in get_path_from_regex (:pr:`49`, thanks to :ghuser:`blueyed`)
|
- **FIXED:** fixed an exception caused by a warning in get_path_from_regex (:pr:`49`, thanks to :ghuser:`blueyed`)
|
||||||
|
|||||||
+25
-2
@@ -9,6 +9,31 @@ Custom schema generation
|
|||||||
If the default spec generation does not quite match what you were hoping to achieve, ``drf-yasg`` provides some
|
If the default spec generation does not quite match what you were hoping to achieve, ``drf-yasg`` provides some
|
||||||
custom behavior hooks by default.
|
custom behavior hooks by default.
|
||||||
|
|
||||||
|
.. _custom-spec-excluding-endpoints:
|
||||||
|
|
||||||
|
*******************
|
||||||
|
Excluding endpoints
|
||||||
|
*******************
|
||||||
|
|
||||||
|
You can prevent a view from being included in the Swagger view by setting its class-level ``swagger_schema``
|
||||||
|
attribute to ``None``, or you can prevent an operation from being included by setting its ``auto_schema`` override
|
||||||
|
to none in :ref:`@swagger_auto_schema <custom-spec-swagger-auto-schema>`:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class UserList(APIView):
|
||||||
|
swagger_schema = None
|
||||||
|
|
||||||
|
# all methods of the UserList class will be excluded
|
||||||
|
...
|
||||||
|
|
||||||
|
# only the GET method will be shown in Swagger
|
||||||
|
@swagger_auto_schema(method='put', auto_schema=None)
|
||||||
|
@swagger_auto_schema(methods=['get'], ...)
|
||||||
|
@api_view(['GET', 'PUT'])
|
||||||
|
def user_detail(request, pk):
|
||||||
|
pass
|
||||||
|
|
||||||
.. _custom-spec-swagger-auto-schema:
|
.. _custom-spec-swagger-auto-schema:
|
||||||
|
|
||||||
**************************************
|
**************************************
|
||||||
@@ -200,8 +225,6 @@ This custom generator can be put to use by setting it as the :attr:`.generator_c
|
|||||||
``Inspector`` classes
|
``Inspector`` classes
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
.. versionadded:: 1.1
|
|
||||||
|
|
||||||
For customizing behavior related to specific field, serializer, filter or paginator classes you can implement the
|
For customizing behavior related to specific field, serializer, filter or paginator classes you can implement the
|
||||||
:class:`~.inspectors.FieldInspector`, :class:`~.inspectors.SerializerInspector`, :class:`~.inspectors.FilterInspector`,
|
:class:`~.inspectors.FieldInspector`, :class:`~.inspectors.SerializerInspector`, :class:`~.inspectors.FilterInspector`,
|
||||||
:class:`~.inspectors.PaginatorInspector` classes and use them with
|
:class:`~.inspectors.PaginatorInspector` classes and use them with
|
||||||
|
|||||||
+19
-3
@@ -6,7 +6,6 @@
|
|||||||
Functional overview
|
Functional overview
|
||||||
**********************
|
**********************
|
||||||
|
|
||||||
|
|
||||||
------------------------------
|
------------------------------
|
||||||
OpenAPI specification overview
|
OpenAPI specification overview
|
||||||
------------------------------
|
------------------------------
|
||||||
@@ -155,9 +154,26 @@ This section describes where information is sourced from when using the default
|
|||||||
|
|
||||||
Other versioning schemes are not presently supported.
|
Other versioning schemes are not presently supported.
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
A note on limitations
|
||||||
|
---------------------
|
||||||
|
|
||||||
.. versionadded:: 1.2
|
When schema generation is requested, available endpoints are inspected by enumeration all the routes registered in
|
||||||
Base path and versioning support.
|
Django's urlconf. Each registered view is then artificially instantiated for introspection, and it is this step that
|
||||||
|
brings some limitations to what can be done:
|
||||||
|
|
||||||
|
* the ``request`` the view sees will always be the request made against the schema view endpoint
|
||||||
|
- e.g. ``GET /swagger.yaml``
|
||||||
|
* path parameters will not be filled
|
||||||
|
|
||||||
|
This means that you could get surprizing results if your ``get_serializer`` or ``get_serializer_class`` methods
|
||||||
|
depend on the incoming request, call ``get_object`` or in general depend on any stateful logic. You can prevent this
|
||||||
|
in a few ways:
|
||||||
|
|
||||||
|
* provide a fixed serializer for request and response body introspection using
|
||||||
|
:ref:`@swagger_auto_schema <custom-spec-swagger-auto-schema>`, to prevent ``get_serializer`` from being called on
|
||||||
|
the view
|
||||||
|
* :ref:`exclude your endpoint from introspection <custom-spec-excluding-endpoints>`
|
||||||
|
|
||||||
.. _SCRIPT_NAME: https://www.python.org/dev/peps/pep-0333/#environ-variables
|
.. _SCRIPT_NAME: https://www.python.org/dev/peps/pep-0333/#environ-variables
|
||||||
.. _FORCE_SCRIPT_NAME: https://docs.djangoproject.com/en/2.0/ref/settings/#force-script-name
|
.. _FORCE_SCRIPT_NAME: https://docs.djangoproject.com/en/2.0/ref/settings/#force-script-name
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ You can use your custom renderer classes as kwargs to :meth:`.SchemaView.as_cach
|
|||||||
Management command
|
Management command
|
||||||
******************
|
******************
|
||||||
|
|
||||||
.. versionadded:: 1.1.1
|
|
||||||
|
|
||||||
If you only need a swagger spec file in YAML or JSON format, you can use the ``generate_swagger`` management command
|
If you only need a swagger spec file in YAML or JSON format, you can use the ``generate_swagger`` management command
|
||||||
to get it without having to start the web server:
|
to get it without having to start the web server:
|
||||||
|
|
||||||
|
|||||||
+28
-12
@@ -10,13 +10,14 @@ from rest_framework.compat import URLPattern, URLResolver, get_original_route
|
|||||||
from rest_framework.schemas.generators import EndpointEnumerator as _EndpointEnumerator
|
from rest_framework.schemas.generators import EndpointEnumerator as _EndpointEnumerator
|
||||||
from rest_framework.schemas.generators import SchemaGenerator, endpoint_ordering
|
from rest_framework.schemas.generators import SchemaGenerator, endpoint_ordering
|
||||||
from rest_framework.schemas.inspectors import get_pk_description
|
from rest_framework.schemas.inspectors import get_pk_description
|
||||||
|
from rest_framework.settings import api_settings as rest_framework_settings
|
||||||
from drf_yasg.errors import SwaggerGenerationError
|
|
||||||
|
|
||||||
from . import openapi
|
from . import openapi
|
||||||
from .app_settings import swagger_settings
|
from .app_settings import swagger_settings
|
||||||
|
from .errors import SwaggerGenerationError
|
||||||
from .inspectors.field import get_basic_type_info, get_queryset_field
|
from .inspectors.field import get_basic_type_info, get_queryset_field
|
||||||
from .openapi import ReferenceResolver
|
from .openapi import ReferenceResolver
|
||||||
|
from .utils import get_consumes, get_produces
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -44,6 +45,9 @@ class EndpointEnumerator(_EndpointEnumerator):
|
|||||||
if version and version not in namespace.split(':'):
|
if version and version not in namespace.split(':'):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
if getattr(callback.cls, 'swagger_schema', object()) is None:
|
||||||
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def replace_version(self, path, callback):
|
def replace_version(self, path, callback):
|
||||||
@@ -165,6 +169,9 @@ class OpenAPISchemaGenerator(object):
|
|||||||
self._gen = SchemaGenerator(info.title, url, info.get('description', ''), patterns, urlconf)
|
self._gen = SchemaGenerator(info.title, url, info.get('description', ''), patterns, urlconf)
|
||||||
self.info = info
|
self.info = info
|
||||||
self.version = version
|
self.version = version
|
||||||
|
self.consumes = []
|
||||||
|
self.produces = []
|
||||||
|
|
||||||
if url is None and swagger_settings.DEFAULT_API_URL is not None:
|
if url is None and swagger_settings.DEFAULT_API_URL is not None:
|
||||||
url = swagger_settings.DEFAULT_API_URL
|
url = swagger_settings.DEFAULT_API_URL
|
||||||
|
|
||||||
@@ -191,22 +198,24 @@ class OpenAPISchemaGenerator(object):
|
|||||||
"""
|
"""
|
||||||
endpoints = self.get_endpoints(request)
|
endpoints = self.get_endpoints(request)
|
||||||
components = ReferenceResolver(openapi.SCHEMA_DEFINITIONS)
|
components = ReferenceResolver(openapi.SCHEMA_DEFINITIONS)
|
||||||
|
self.consumes = get_consumes(rest_framework_settings.DEFAULT_PARSER_CLASSES)
|
||||||
|
self.produces = get_produces(rest_framework_settings.DEFAULT_RENDERER_CLASSES)
|
||||||
paths, prefix = self.get_paths(endpoints, components, request, public)
|
paths, prefix = self.get_paths(endpoints, components, request, public)
|
||||||
|
|
||||||
|
security_definitions = swagger_settings.SECURITY_DEFINITIONS
|
||||||
|
security_requirements = swagger_settings.SECURITY_REQUIREMENTS
|
||||||
|
if security_requirements is None:
|
||||||
|
security_requirements = [{security_scheme: [] for security_scheme in swagger_settings.SECURITY_DEFINITIONS}]
|
||||||
|
|
||||||
url = self.url
|
url = self.url
|
||||||
if url is None and request is not None:
|
if url is None and request is not None:
|
||||||
url = request.build_absolute_uri()
|
url = request.build_absolute_uri()
|
||||||
|
|
||||||
swagger = openapi.Swagger(
|
return openapi.Swagger(
|
||||||
info=self.info, paths=paths,
|
info=self.info, paths=paths, consumes=self.consumes or None, produces=self.produces or None,
|
||||||
|
security_definitions=security_definitions, security=security_requirements,
|
||||||
_url=url, _prefix=prefix, _version=self.version, **dict(components)
|
_url=url, _prefix=prefix, _version=self.version, **dict(components)
|
||||||
)
|
)
|
||||||
swagger.security_definitions = swagger_settings.SECURITY_DEFINITIONS
|
|
||||||
security_requirements = swagger_settings.SECURITY_REQUIREMENTS
|
|
||||||
if security_requirements is None:
|
|
||||||
security_requirements = [{security_scheme: [] for security_scheme in swagger_settings.SECURITY_DEFINITIONS}]
|
|
||||||
swagger.security = security_requirements
|
|
||||||
return swagger
|
|
||||||
|
|
||||||
def create_view(self, callback, method, request=None):
|
def create_view(self, callback, method, request=None):
|
||||||
"""Create a view instance from a view callback as registered in urlpatterns.
|
"""Create a view instance from a view callback as registered in urlpatterns.
|
||||||
@@ -330,7 +339,6 @@ class OpenAPISchemaGenerator(object):
|
|||||||
:param Request request: the request made against the schema view; can be None
|
:param Request request: the request made against the schema view; can be None
|
||||||
:rtype: openapi.Operation
|
:rtype: openapi.Operation
|
||||||
"""
|
"""
|
||||||
|
|
||||||
operation_keys = self.get_operation_keys(path[len(prefix):], method, view)
|
operation_keys = self.get_operation_keys(path[len(prefix):], method, view)
|
||||||
overrides = self.get_overrides(view, method)
|
overrides = self.get_overrides(view, method)
|
||||||
|
|
||||||
@@ -342,8 +350,16 @@ class OpenAPISchemaGenerator(object):
|
|||||||
# 3. on the swagger_auto_schema decorator
|
# 3. on the swagger_auto_schema decorator
|
||||||
view_inspector_cls = overrides.get('auto_schema', view_inspector_cls)
|
view_inspector_cls = overrides.get('auto_schema', view_inspector_cls)
|
||||||
|
|
||||||
|
if view_inspector_cls is None:
|
||||||
|
return None
|
||||||
|
|
||||||
view_inspector = view_inspector_cls(view, path, method, components, request, overrides)
|
view_inspector = view_inspector_cls(view, path, method, components, request, overrides)
|
||||||
return view_inspector.get_operation(operation_keys)
|
operation = view_inspector.get_operation(operation_keys)
|
||||||
|
if set(operation.consumes) == set(self.consumes):
|
||||||
|
del operation.consumes
|
||||||
|
if set(operation.produces) == set(self.produces):
|
||||||
|
del operation.produces
|
||||||
|
return operation
|
||||||
|
|
||||||
def get_path_item(self, path, view_cls, operations):
|
def get_path_item(self, path, view_cls, operations):
|
||||||
"""Get a :class:`.PathItem` object that describes the parameters and operations related to a single path in the
|
"""Get a :class:`.PathItem` object that describes the parameters and operations related to a single path in the
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ from rest_framework.status import is_success
|
|||||||
|
|
||||||
from .. import openapi
|
from .. import openapi
|
||||||
from ..errors import SwaggerGenerationError
|
from ..errors import SwaggerGenerationError
|
||||||
from ..utils import force_serializer_instance, guess_response_status, is_list_view, no_body, param_list_to_odict
|
from ..utils import (
|
||||||
|
force_serializer_instance, get_consumes, get_produces, guess_response_status, is_list_view, no_body,
|
||||||
|
param_list_to_odict
|
||||||
|
)
|
||||||
from .base import ViewInspector
|
from .base import ViewInspector
|
||||||
|
|
||||||
|
|
||||||
@@ -18,6 +21,7 @@ class SwaggerAutoSchema(ViewInspector):
|
|||||||
|
|
||||||
def get_operation(self, operation_keys):
|
def get_operation(self, operation_keys):
|
||||||
consumes = self.get_consumes()
|
consumes = self.get_consumes()
|
||||||
|
produces = self.get_produces()
|
||||||
|
|
||||||
body = self.get_request_body_parameters(consumes)
|
body = self.get_request_body_parameters(consumes)
|
||||||
query = self.get_query_parameters()
|
query = self.get_query_parameters()
|
||||||
@@ -39,6 +43,7 @@ class SwaggerAutoSchema(ViewInspector):
|
|||||||
responses=responses,
|
responses=responses,
|
||||||
parameters=parameters,
|
parameters=parameters,
|
||||||
consumes=consumes,
|
consumes=consumes,
|
||||||
|
produces=produces,
|
||||||
tags=tags,
|
tags=tags,
|
||||||
security=security
|
security=security
|
||||||
)
|
)
|
||||||
@@ -91,8 +96,8 @@ class SwaggerAutoSchema(ViewInspector):
|
|||||||
if body_override is no_body:
|
if body_override is no_body:
|
||||||
return None
|
return None
|
||||||
if self.method not in self.body_methods:
|
if self.method not in self.body_methods:
|
||||||
raise SwaggerGenerationError("request_body can only be applied to PUT, PATCH or POST views; "
|
raise SwaggerGenerationError("request_body can only be applied to (" + ','.join(self.body_methods) +
|
||||||
"are you looking for query_serializer or manual_parameters?")
|
"); are you looking for query_serializer or manual_parameters?")
|
||||||
if isinstance(body_override, openapi.Schema.OR_REF):
|
if isinstance(body_override, openapi.Schema.OR_REF):
|
||||||
return body_override
|
return body_override
|
||||||
return force_serializer_instance(body_override)
|
return force_serializer_instance(body_override)
|
||||||
@@ -296,7 +301,7 @@ class SwaggerAutoSchema(ViewInspector):
|
|||||||
authentication schemes). Returning ``None`` will inherit the top-level secuirty requirements.
|
authentication schemes). Returning ``None`` will inherit the top-level secuirty requirements.
|
||||||
|
|
||||||
:return: security requirements
|
:return: security requirements
|
||||||
:rtype: list"""
|
:rtype: list[dict[str,list[str]]]"""
|
||||||
return self.overrides.get('security', None)
|
return self.overrides.get('security', None)
|
||||||
|
|
||||||
def get_tags(self, operation_keys):
|
def get_tags(self, operation_keys):
|
||||||
@@ -314,7 +319,11 @@ class SwaggerAutoSchema(ViewInspector):
|
|||||||
|
|
||||||
:rtype: list[str]
|
:rtype: list[str]
|
||||||
"""
|
"""
|
||||||
media_types = [parser.media_type for parser in getattr(self.view, 'parser_classes', [])]
|
return get_consumes(getattr(self.view, 'parser_classes', []))
|
||||||
if all(is_form_media_type(encoding) for encoding in media_types):
|
|
||||||
return media_types
|
def get_produces(self):
|
||||||
return media_types[:1]
|
"""Return the MIME types this endpoint can produce.
|
||||||
|
|
||||||
|
:rtype: list[str]
|
||||||
|
"""
|
||||||
|
return get_produces(getattr(self.view, 'renderer_classes', []))
|
||||||
|
|||||||
+14
-3
@@ -211,7 +211,8 @@ class Info(SwaggerDict):
|
|||||||
|
|
||||||
|
|
||||||
class Swagger(SwaggerDict):
|
class Swagger(SwaggerDict):
|
||||||
def __init__(self, info=None, _url=None, _prefix=None, _version=None, paths=None, definitions=None, **extra):
|
def __init__(self, info=None, _url=None, _prefix=None, _version=None, consumes=None, produces=None,
|
||||||
|
security_definitions=None, security=None, paths=None, definitions=None, **extra):
|
||||||
"""Root Swagger object.
|
"""Root Swagger object.
|
||||||
|
|
||||||
:param .Info info: info object
|
:param .Info info: info object
|
||||||
@@ -219,6 +220,10 @@ class Swagger(SwaggerDict):
|
|||||||
:param str _prefix: api path prefix to use in setting basePath; this will be appended to the wsgi
|
:param str _prefix: api path prefix to use in setting basePath; this will be appended to the wsgi
|
||||||
SCRIPT_NAME prefix or Django's FORCE_SCRIPT_NAME if applicable
|
SCRIPT_NAME prefix or Django's FORCE_SCRIPT_NAME if applicable
|
||||||
:param str _version: version string to override Info
|
:param str _version: version string to override Info
|
||||||
|
:param list[dict] security_definitions: list of supported authentication mechanisms
|
||||||
|
:param list[dict] security: authentication mechanisms accepted by default; can be overriden in Operation
|
||||||
|
:param list[str] consumes: consumed MIME types; can be overriden in Operation
|
||||||
|
:param list[str] produces: produced MIME types; can be overriden in Operation
|
||||||
:param .Paths paths: paths object
|
:param .Paths paths: paths object
|
||||||
:param dict[str,.Schema] definitions: named models
|
:param dict[str,.Schema] definitions: named models
|
||||||
"""
|
"""
|
||||||
@@ -234,6 +239,10 @@ class Swagger(SwaggerDict):
|
|||||||
self.schemes = [url.scheme]
|
self.schemes = [url.scheme]
|
||||||
|
|
||||||
self.base_path = self.get_base_path(get_script_prefix(), _prefix)
|
self.base_path = self.get_base_path(get_script_prefix(), _prefix)
|
||||||
|
self.consumes = consumes
|
||||||
|
self.produces = produces
|
||||||
|
self.security_definitions = filter_none(security_definitions)
|
||||||
|
self.security = filter_none(security)
|
||||||
self.paths = paths
|
self.paths = paths
|
||||||
self.definitions = filter_none(definitions)
|
self.definitions = filter_none(definitions)
|
||||||
self._insert_extras__()
|
self._insert_extras__()
|
||||||
@@ -304,8 +313,8 @@ class PathItem(SwaggerDict):
|
|||||||
|
|
||||||
|
|
||||||
class Operation(SwaggerDict):
|
class Operation(SwaggerDict):
|
||||||
def __init__(self, operation_id, responses, parameters=None, consumes=None,
|
def __init__(self, operation_id, responses, parameters=None, consumes=None, produces=None, summary=None,
|
||||||
produces=None, summary=None, description=None, tags=None, **extra):
|
description=None, tags=None, security=None, **extra):
|
||||||
"""Information about an API operation (path + http method combination)
|
"""Information about an API operation (path + http method combination)
|
||||||
|
|
||||||
:param str operation_id: operation ID, should be unique across all operations
|
:param str operation_id: operation ID, should be unique across all operations
|
||||||
@@ -316,6 +325,7 @@ class Operation(SwaggerDict):
|
|||||||
:param str summary: operation summary; should be < 120 characters
|
:param str summary: operation summary; should be < 120 characters
|
||||||
:param str description: operation description; can be of any length and supports markdown
|
:param str description: operation description; can be of any length and supports markdown
|
||||||
:param list[str] tags: operation tags
|
:param list[str] tags: operation tags
|
||||||
|
:param list[dict[str,list[str]]] security: list of security requirements
|
||||||
"""
|
"""
|
||||||
super(Operation, self).__init__(**extra)
|
super(Operation, self).__init__(**extra)
|
||||||
self.operation_id = operation_id
|
self.operation_id = operation_id
|
||||||
@@ -326,6 +336,7 @@ class Operation(SwaggerDict):
|
|||||||
self.consumes = filter_none(consumes)
|
self.consumes = filter_none(consumes)
|
||||||
self.produces = filter_none(produces)
|
self.produces = filter_none(produces)
|
||||||
self.tags = filter_none(tags)
|
self.tags = filter_none(tags)
|
||||||
|
self.security = filter_none(security)
|
||||||
self._insert_extras__()
|
self._insert_extras__()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+34
-9
@@ -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.request import is_form_media_type
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -11,8 +12,10 @@ logger = logging.getLogger(__name__)
|
|||||||
#: used to forcibly remove the body of a request via :func:`.swagger_auto_schema`
|
#: used to forcibly remove the body of a request via :func:`.swagger_auto_schema`
|
||||||
no_body = object()
|
no_body = object()
|
||||||
|
|
||||||
|
unset = object()
|
||||||
|
|
||||||
def swagger_auto_schema(method=None, methods=None, auto_schema=None, request_body=None, query_serializer=None,
|
|
||||||
|
def swagger_auto_schema(method=None, methods=None, auto_schema=unset, request_body=None, query_serializer=None,
|
||||||
manual_parameters=None, operation_id=None, operation_description=None, security=None,
|
manual_parameters=None, operation_id=None, operation_description=None, security=None,
|
||||||
responses=None, field_inspectors=None, filter_inspectors=None, paginator_inspectors=None,
|
responses=None, field_inspectors=None, filter_inspectors=None, paginator_inspectors=None,
|
||||||
**extra_overrides):
|
**extra_overrides):
|
||||||
@@ -23,17 +26,11 @@ def swagger_auto_schema(method=None, methods=None, auto_schema=None, request_bod
|
|||||||
|
|
||||||
The `auto_schema` and `operation_description` arguments take precendence over view- or method-level values.
|
The `auto_schema` and `operation_description` arguments take precendence over view- or method-level values.
|
||||||
|
|
||||||
.. versionchanged:: 1.1
|
|
||||||
Added the ``extra_overrides`` and ``operatiod_id`` parameters.
|
|
||||||
|
|
||||||
.. versionchanged:: 1.1
|
|
||||||
Added the ``field_inspectors``, ``filter_inspectors`` and ``paginator_inspectors`` parameters.
|
|
||||||
|
|
||||||
:param str method: for multi-method views, the http method the options should apply to
|
:param str method: for multi-method views, the http method the options should apply to
|
||||||
:param list[str] methods: for multi-method views, the http methods the options should apply to
|
:param list[str] methods: for multi-method views, the http methods the options should apply to
|
||||||
:param .inspectors.SwaggerAutoSchema auto_schema: custom class to use for generating the Operation object;
|
:param .inspectors.SwaggerAutoSchema auto_schema: custom class to use for generating the Operation object;
|
||||||
this overrides both the class-level ``swagger_schema`` attribute and the ``DEFAULT_AUTO_SCHEMA_CLASS``
|
this overrides both the class-level ``swagger_schema`` attribute and the ``DEFAULT_AUTO_SCHEMA_CLASS``
|
||||||
setting
|
setting, and can be set to ``None`` to prevent this operation from being generated
|
||||||
:param .Schema,.SchemaRef,.Serializer request_body: custom request body, or :data:`.no_body`. The value given here
|
:param .Schema,.SchemaRef,.Serializer request_body: custom request body, or :data:`.no_body`. The value given here
|
||||||
will be used as the ``schema`` property of a :class:`.Parameter` with ``in: 'body'``.
|
will be used as the ``schema`` property of a :class:`.Parameter` with ``in: 'body'``.
|
||||||
|
|
||||||
@@ -91,7 +88,6 @@ 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"
|
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,
|
|
||||||
'request_body': request_body,
|
'request_body': request_body,
|
||||||
'query_serializer': query_serializer,
|
'query_serializer': query_serializer,
|
||||||
'manual_parameters': manual_parameters,
|
'manual_parameters': manual_parameters,
|
||||||
@@ -104,6 +100,8 @@ def swagger_auto_schema(method=None, methods=None, auto_schema=None, request_bod
|
|||||||
'field_inspectors': list(field_inspectors) if field_inspectors else None,
|
'field_inspectors': list(field_inspectors) if field_inspectors else None,
|
||||||
}
|
}
|
||||||
data = filter_none(data)
|
data = filter_none(data)
|
||||||
|
if auto_schema is not unset:
|
||||||
|
data['auto_schema'] = auto_schema
|
||||||
data.update(extra_overrides)
|
data.update(extra_overrides)
|
||||||
if not data: # pragma: no cover
|
if not data: # pragma: no cover
|
||||||
# no overrides to set, no use in doing more work
|
# no overrides to set, no use in doing more work
|
||||||
@@ -248,3 +246,30 @@ def force_serializer_instance(serializer):
|
|||||||
assert isinstance(serializer, serializers.BaseSerializer), \
|
assert isinstance(serializer, serializers.BaseSerializer), \
|
||||||
"Serializer class or instance required, not %s" % type(serializer).__name__
|
"Serializer class or instance required, not %s" % type(serializer).__name__
|
||||||
return serializer
|
return serializer
|
||||||
|
|
||||||
|
|
||||||
|
def get_consumes(parser_classes):
|
||||||
|
"""Extract ``consumes`` MIME types from a list of parser classes.
|
||||||
|
|
||||||
|
:param list parser_classes: parser classes
|
||||||
|
:return: MIME types for ``consumes``
|
||||||
|
:rtype: list[str]
|
||||||
|
"""
|
||||||
|
media_types = [parser.media_type for parser in parser_classes or []]
|
||||||
|
if all(is_form_media_type(encoding) for encoding in media_types):
|
||||||
|
return media_types
|
||||||
|
else:
|
||||||
|
media_types = [encoding for encoding in media_types if not is_form_media_type(encoding)]
|
||||||
|
return media_types
|
||||||
|
|
||||||
|
|
||||||
|
def get_produces(renderer_classes):
|
||||||
|
"""Extract ``produces`` MIME types from a list of renderer classes.
|
||||||
|
|
||||||
|
:param list renderer_classes: renderer classes
|
||||||
|
:return: MIME types for ``produces``
|
||||||
|
:rtype: list[str]
|
||||||
|
"""
|
||||||
|
media_types = [renderer.media_type for renderer in renderer_classes or []]
|
||||||
|
media_types = [encoding for encoding in media_types if 'html' not in encoding]
|
||||||
|
return media_types
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from djangorestframework_camel_case.parser import CamelCaseJSONParser
|
|||||||
from djangorestframework_camel_case.render import CamelCaseJSONRenderer
|
from djangorestframework_camel_case.render import CamelCaseJSONRenderer
|
||||||
from inflection import camelize
|
from inflection import camelize
|
||||||
from rest_framework import generics
|
from rest_framework import generics
|
||||||
|
from rest_framework.parsers import FormParser
|
||||||
|
|
||||||
from drf_yasg import openapi
|
from drf_yasg import openapi
|
||||||
from drf_yasg.inspectors import SwaggerAutoSchema
|
from drf_yasg.inspectors import SwaggerAutoSchema
|
||||||
@@ -21,7 +22,7 @@ class SnippetList(generics.ListCreateAPIView):
|
|||||||
queryset = Snippet.objects.all()
|
queryset = Snippet.objects.all()
|
||||||
serializer_class = SnippetSerializer
|
serializer_class = SnippetSerializer
|
||||||
|
|
||||||
parser_classes = (CamelCaseJSONParser,)
|
parser_classes = (FormParser, CamelCaseJSONParser,)
|
||||||
renderer_classes = (CamelCaseJSONRenderer,)
|
renderer_classes = (CamelCaseJSONRenderer,)
|
||||||
swagger_schema = CamelCaseOperationIDAutoSchema
|
swagger_schema = CamelCaseOperationIDAutoSchema
|
||||||
|
|
||||||
|
|||||||
+9
-43
@@ -16,6 +16,15 @@ host: test.local:8002
|
|||||||
schemes:
|
schemes:
|
||||||
- http
|
- http
|
||||||
basePath: /
|
basePath: /
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
securityDefinitions:
|
||||||
|
basic:
|
||||||
|
type: basic
|
||||||
|
security:
|
||||||
|
- basic: []
|
||||||
paths:
|
paths:
|
||||||
/articles/:
|
/articles/:
|
||||||
get:
|
get:
|
||||||
@@ -63,8 +72,6 @@ paths:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/Article'
|
$ref: '#/definitions/Article'
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- articles
|
- articles
|
||||||
post:
|
post:
|
||||||
@@ -81,8 +88,6 @@ paths:
|
|||||||
description: ''
|
description: ''
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Article'
|
$ref: '#/definitions/Article'
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- articles
|
- articles
|
||||||
parameters: []
|
parameters: []
|
||||||
@@ -108,8 +113,6 @@ paths:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/Article'
|
$ref: '#/definitions/Article'
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- articles
|
- articles
|
||||||
parameters: []
|
parameters: []
|
||||||
@@ -123,8 +126,6 @@ paths:
|
|||||||
description: ''
|
description: ''
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Article'
|
$ref: '#/definitions/Article'
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- articles
|
- articles
|
||||||
put:
|
put:
|
||||||
@@ -141,8 +142,6 @@ paths:
|
|||||||
description: ''
|
description: ''
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Article'
|
$ref: '#/definitions/Article'
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- articles
|
- articles
|
||||||
patch:
|
patch:
|
||||||
@@ -161,8 +160,6 @@ paths:
|
|||||||
$ref: '#/definitions/Article'
|
$ref: '#/definitions/Article'
|
||||||
'404':
|
'404':
|
||||||
description: slug not found
|
description: slug not found
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- articles
|
- articles
|
||||||
delete:
|
delete:
|
||||||
@@ -172,8 +169,6 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
'204':
|
'204':
|
||||||
description: ''
|
description: ''
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- articles
|
- articles
|
||||||
parameters:
|
parameters:
|
||||||
@@ -246,8 +241,6 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: ''
|
description: ''
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- plain
|
- plain
|
||||||
parameters: []
|
parameters: []
|
||||||
@@ -263,8 +256,6 @@ paths:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/Snippet'
|
$ref: '#/definitions/Snippet'
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- snippets
|
- snippets
|
||||||
post:
|
post:
|
||||||
@@ -281,8 +272,6 @@ paths:
|
|||||||
description: ''
|
description: ''
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Snippet'
|
$ref: '#/definitions/Snippet'
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- snippets
|
- snippets
|
||||||
parameters: []
|
parameters: []
|
||||||
@@ -296,8 +285,6 @@ paths:
|
|||||||
description: ''
|
description: ''
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Snippet'
|
$ref: '#/definitions/Snippet'
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- snippets
|
- snippets
|
||||||
put:
|
put:
|
||||||
@@ -314,8 +301,6 @@ paths:
|
|||||||
description: ''
|
description: ''
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Snippet'
|
$ref: '#/definitions/Snippet'
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- snippets
|
- snippets
|
||||||
patch:
|
patch:
|
||||||
@@ -332,8 +317,6 @@ paths:
|
|||||||
description: ''
|
description: ''
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Snippet'
|
$ref: '#/definitions/Snippet'
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- snippets
|
- snippets
|
||||||
delete:
|
delete:
|
||||||
@@ -348,8 +331,6 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
'204':
|
'204':
|
||||||
description: ''
|
description: ''
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- snippets
|
- snippets
|
||||||
parameters:
|
parameters:
|
||||||
@@ -380,8 +361,6 @@ paths:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/UserSerializerrr'
|
$ref: '#/definitions/UserSerializerrr'
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- users
|
- users
|
||||||
post:
|
post:
|
||||||
@@ -408,8 +387,6 @@ paths:
|
|||||||
properties:
|
properties:
|
||||||
username:
|
username:
|
||||||
type: string
|
type: string
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- users
|
- users
|
||||||
security: []
|
security: []
|
||||||
@@ -420,8 +397,6 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: ''
|
description: ''
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- users
|
- users
|
||||||
parameters: []
|
parameters: []
|
||||||
@@ -439,8 +414,6 @@ paths:
|
|||||||
description: response description
|
description: response description
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/UserSerializerrr'
|
$ref: '#/definitions/UserSerializerrr'
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- users
|
- users
|
||||||
put:
|
put:
|
||||||
@@ -457,8 +430,6 @@ paths:
|
|||||||
description: ''
|
description: ''
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/UserSerializerrr'
|
$ref: '#/definitions/UserSerializerrr'
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
tags:
|
tags:
|
||||||
- users
|
- users
|
||||||
parameters:
|
parameters:
|
||||||
@@ -1121,8 +1092,3 @@ definitions:
|
|||||||
pattern: ^[-a-zA-Z0-9_]+$
|
pattern: ^[-a-zA-Z0-9_]+$
|
||||||
readOnly: true
|
readOnly: true
|
||||||
uniqueItems: true
|
uniqueItems: true
|
||||||
securityDefinitions:
|
|
||||||
basic:
|
|
||||||
type: basic
|
|
||||||
security:
|
|
||||||
- basic: []
|
|
||||||
|
|||||||
Reference in New Issue
Block a user