parent
f81795d745
commit
68b0dda0b9
|
|
@ -3,6 +3,14 @@ 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**
|
**1.1.2**
|
||||||
*********
|
*********
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue