Compare commits

..

7 Commits

Author SHA1 Message Date
Cristi Vîjdea 6ea8711a1f Fix in-place modification of swagger_auto_schema arguments (#75)
Fixes #74
2018-03-05 11:51:51 +02:00
Cristi Vîjdea ee46f59fb1 Infer ChoiceField type from model field when in ModelSerializer
Fixes part of issue #69
2018-02-26 20:32:57 +02:00
Santiago Castro 3f7ad62950 Make 1.10.0 the min six version (#71) 2018-02-26 17:18:52 +02:00
Cristi Vîjdea b38d3e6805 Do not set pattern on non-string values
Fixes #68
2018-02-23 18:51:55 +02:00
Cristi Vîjdea 058fd7096d Change README link from pypi.python.org to pypi.org
Description rendering is prettier on the new version.
2018-02-22 20:46:26 +02:00
Cristi Vîjdea a32321d43a Add release dates to changelog 2018-02-22 20:46:22 +02:00
Cristi Vîjdea f15e70b7db Fix missing assignment for default in openapi.Parameter 2018-02-22 20:33:47 +02:00
14 changed files with 180 additions and 25 deletions
+3 -3
View File
@@ -13,9 +13,9 @@
</component> </component>
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/testproj" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/testproj" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/venv" />
</content> </content>
<orderEntry type="jdk" jdkName="Python 3.6 (drf-yasg)" jdkType="Python SDK" /> <orderEntry type="jdk" jdkName="Python 3.6 (drf-yasg)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
@@ -24,7 +24,7 @@
<option name="TEMPLATE_CONFIGURATION" value="Django" /> <option name="TEMPLATE_CONFIGURATION" value="Django" />
<option name="TEMPLATE_FOLDERS"> <option name="TEMPLATE_FOLDERS">
<list> <list>
<option value="$MODULE_DIR$/drf_yasg/templates" /> <option value="$MODULE_DIR$/src/drf_yasg/templates" />
</list> </list>
</option> </option>
</component> </component>
@@ -32,4 +32,4 @@
<option name="projectConfiguration" value="py.test" /> <option name="projectConfiguration" value="py.test" />
<option name="PROJECT_TEST_RUNNER" value="py.test" /> <option name="PROJECT_TEST_RUNNER" value="py.test" />
</component> </component>
</module> </module>
+1 -1
View File
@@ -362,7 +362,7 @@ provided out of the box - if you have ``djangorestframework-camel-case`` install
:alt: Codecov :alt: Codecov
.. |pypi-version| image:: https://img.shields.io/pypi/v/drf-yasg.svg .. |pypi-version| image:: https://img.shields.io/pypi/v/drf-yasg.svg
:target: https://pypi.python.org/pypi/drf-yasg/ :target: https://pypi.org/project/drf-yasg/
:alt: PyPI :alt: PyPI
.. |rtd-badge| image:: https://img.shields.io/readthedocs/drf-yasg.svg .. |rtd-badge| image:: https://img.shields.io/readthedocs/drf-yasg.svg
+64
View File
@@ -2,10 +2,42 @@
Changelog Changelog
######### #########
*********
**1.4.5**
*********
*Release date: Mar 05, 2018*
- **FIXED:** fixed an issue with modification of ``swagger_auto_schema`` arguments in-place during introspection, which
would sometimes cause an incomplete Swagger document to be generated after the first pass (:issue:`74`, :pr:`75`)
*********
**1.4.4**
*********
*Release date: Feb 26, 2018*
- **IMPROVED:** ``type`` for ``ChoiceField`` generated by a ``ModelSerializer`` from a model field with ``choices=...``
will now be set according to the associated model field (:issue:`69`)
- **FIXED:** ``lookup_field`` and ``lookup_value_regex`` on the same ``ViewSet`` will no longer trigger an exception
(:issue:`68`)
*********
**1.4.3**
*********
*Release date: Feb 22, 2018*
- **FIXED:** added a missing assignment that would cause the ``default`` argument to ``openapi.Parameter.__init__`` to
be ignored
********* *********
**1.4.2** **1.4.2**
********* *********
*Release date: Feb 22, 2018*
- **FIXED:** fixed a bug that causes a ``ModelViewSet`` generated from models with nested ``ForeignKey`` to output - **FIXED:** fixed a bug that causes a ``ModelViewSet`` generated from models with nested ``ForeignKey`` to output
models named ``Nested`` into the ``definitions`` section (:issue:`59`, :pr:`65`) models named ``Nested`` into the ``definitions`` section (:issue:`59`, :pr:`65`)
- **FIXED:** ``Response`` objects without a ``schema`` are now properly handled when passed through - **FIXED:** ``Response`` objects without a ``schema`` are now properly handled when passed through
@@ -15,6 +47,8 @@ Changelog
**1.4.1** **1.4.1**
********* *********
*Release date: Feb 21, 2018*
- **FIXED:** the ``coerce_to_string`` is now respected when setting the type, default value and min/max values of - **FIXED:** the ``coerce_to_string`` is now respected when setting the type, default value and min/max values of
``DecimalField`` in the OpenAPI schema (:issue:`62`) ``DecimalField`` in the OpenAPI schema (:issue:`62`)
- **FIXED:** error responses from web UI views are now rendered with ``TemplateHTMLRenderer`` instead of throwing - **FIXED:** error responses from web UI views are now rendered with ``TemplateHTMLRenderer`` instead of throwing
@@ -26,6 +60,8 @@ Changelog
**1.4.0** **1.4.0**
********* *********
*Release date: Feb 04, 2018*
- **ADDED:** added settings for OAuth2 client configuration in ``swagger-ui`` (:issue:`53`) - **ADDED:** added settings for OAuth2 client configuration in ``swagger-ui`` (:issue:`53`)
- **IMPROVED:** updated ``swagger-ui`` to version 3.9.3 - **IMPROVED:** updated ``swagger-ui`` to version 3.9.3
@@ -33,6 +69,8 @@ Changelog
**1.3.1** **1.3.1**
********* *********
*Release date: Jan 24, 2018*
- **FIXED:** fixed a bug that would sometimes cause endpoints to wrongly be output as form operations (:issue:`50`) - **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 ``produces`` based on renderer classes
- **IMPROVED:** added generation of top-level ``consumes`` and ``produces`` based on - **IMPROVED:** added generation of top-level ``consumes`` and ``produces`` based on
@@ -42,6 +80,8 @@ Changelog
**1.3.0** **1.3.0**
********* *********
*Release date: Jan 23, 2018*
- **ADDED:** security requirements are now correctly set and can be customized; this should fix problems related - **ADDED:** security requirements are now correctly set and can be customized; this should fix 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
@@ -52,6 +92,8 @@ Changelog
**1.2.2** **1.2.2**
********* *********
*Release date: Jan 12, 2018*
- **FIXED:** djangorestframework>=3.7.7 is now required because of breaking changes - **FIXED:** djangorestframework>=3.7.7 is now required because of breaking changes
(:issue:`44`, :pr:`45`, thanks to :ghuser:`h-hirokawa`) (:issue:`44`, :pr:`45`, thanks to :ghuser:`h-hirokawa`)
@@ -59,12 +101,16 @@ Changelog
**1.2.1** **1.2.1**
********* *********
*Release date: Jan 12, 2018*
- Fixed deployment issues - Fixed deployment issues
********* *********
**1.2.0** **1.2.0**
********* *********
*Release date: Jan 12, 2018 (missing from PyPI due to deployment issues)*
- **ADDED:** ``basePath`` is now generated by taking into account the ``SCRIPT_NAME`` variable and the - **ADDED:** ``basePath`` is now generated by taking into account the ``SCRIPT_NAME`` variable and the
longest common prefix of API urls (:issue:`37`, :pr:`42`) longest common prefix of API urls (:issue:`37`, :pr:`42`)
- **IMPROVED:** removed inline scripts and styles from bundled HTML templates to increase CSP compatibility - **IMPROVED:** removed inline scripts and styles from bundled HTML templates to increase CSP compatibility
@@ -76,6 +122,8 @@ Changelog
**1.1.3** **1.1.3**
********* *********
*Release date: Jan 02, 2018*
- **FIXED:** schema view cache will now always ``Vary`` on the ``Cookie`` and ``Authentication`` (the - **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 ``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 authentication in ``swagger-ui`` and ``CurrentUserDefault`` values in the schema
@@ -84,6 +132,8 @@ Changelog
**1.1.2** **1.1.2**
********* *********
*Release date: Jan 01, 2018*
- **IMPROVED:** updated ``swagger-ui`` to version 3.8.1 - **IMPROVED:** updated ``swagger-ui`` to version 3.8.1
- **IMPROVED:** removed some unneeded static files - **IMPROVED:** removed some unneeded static files
@@ -91,6 +141,8 @@ Changelog
**1.1.1** **1.1.1**
********* *********
*Release date: Dec 27, 2017*
- **ADDED:** :ref:`generate_swagger management command <management-command>` - **ADDED:** :ref:`generate_swagger management command <management-command>`
(:issue:`29`, :pr:`31`, thanks to :ghuser:`beaugunderson`) (:issue:`29`, :pr:`31`, thanks to :ghuser:`beaugunderson`)
- **FIXED:** fixed improper generation of ``\Z`` regex tokens - will now be repalced by ``$`` - **FIXED:** fixed improper generation of ``\Z`` regex tokens - will now be repalced by ``$``
@@ -99,6 +151,8 @@ Changelog
**1.1.0** **1.1.0**
********* *********
*Release date: Dec 27, 2017*
- **ADDED:** added support for APIs versioned with ``URLPathVersioning`` or ``NamespaceVersioning`` - **ADDED:** added support for APIs versioned with ``URLPathVersioning`` or ``NamespaceVersioning``
- **ADDED:** added ability to recursively customize schema generation - **ADDED:** added ability to recursively customize schema generation
:ref:`using pluggable inspector classes <custom-spec-inspectors>` :ref:`using pluggable inspector classes <custom-spec-inspectors>`
@@ -114,6 +168,8 @@ Changelog
**1.0.6** **1.0.6**
********* *********
*Release date: Dec 23, 2017*
- **FIXED:** Swagger UI "Try it out!" should now work with Django login - **FIXED:** Swagger UI "Try it out!" should now work with Django login
- **FIXED:** callable ``default`` values on serializer fields will now be properly called (:pr:`24`, :issue:`25`) - **FIXED:** callable ``default`` values on serializer fields will now be properly called (:pr:`24`, :issue:`25`)
- **IMPROVED:** updated ``swagger-ui`` to version 3.8.0 - **IMPROVED:** updated ``swagger-ui`` to version 3.8.0
@@ -125,6 +181,8 @@ Changelog
**1.0.5** **1.0.5**
********* *********
*Release date: Dec 18, 2017*
- **FIXED:** fixed a crash caused by having read-only Serializers nested by reference - **FIXED:** fixed a crash caused by having read-only Serializers nested by reference
- **FIXED:** removed erroneous backslashes in paths when routes are generated using Django 2 - **FIXED:** removed erroneous backslashes in paths when routes are generated using Django 2
`path() <https://docs.djangoproject.com/en/2.0/ref/urls/#django.urls.path>`_ `path() <https://docs.djangoproject.com/en/2.0/ref/urls/#django.urls.path>`_
@@ -136,6 +194,8 @@ Changelog
**1.0.4** **1.0.4**
********* *********
*Release date: Dec 16, 2017*
- **FIXED:** fixed improper generation of YAML references - **FIXED:** fixed improper generation of YAML references
- **ADDED:** added ``query_serializer`` parameter to - **ADDED:** added ``query_serializer`` parameter to
:func:`@swagger_auto_schema <.swagger_auto_schema>` (:issue:`16`, :pr:`17`) :func:`@swagger_auto_schema <.swagger_auto_schema>` (:issue:`16`, :pr:`17`)
@@ -144,6 +204,8 @@ Changelog
**1.0.3** **1.0.3**
********* *********
*Release date: Dec 15, 2017*
- **FIXED:** fixed bug that caused schema views returned from cache to fail (:issue:`14`) - **FIXED:** fixed bug that caused schema views returned from cache to fail (:issue:`14`)
- **FIXED:** disabled automatic generation of response schemas for form operations to avoid confusing errors caused by - **FIXED:** disabled automatic generation of response schemas for form operations to avoid confusing errors caused by
attempting to shove file parameters into Schema objects attempting to shove file parameters into Schema objects
@@ -152,4 +214,6 @@ Changelog
**1.0.2** **1.0.2**
********* *********
*Release date: Dec 13, 2017*
- First published version - First published version
+1 -1
View File
@@ -4,7 +4,7 @@ openapi_codec>=1.3.2
ruamel.yaml>=0.15.34 ruamel.yaml>=0.15.34
inflection>=0.3.1 inflection>=0.3.1
future>=0.16.0 future>=0.16.0
six>=1.11.0 six>=1.10.0
uritemplate>=3.0.0 uritemplate>=3.0.0
djangorestframework>=3.7.7 djangorestframework>=3.7.7
+4 -3
View File
@@ -1,3 +1,4 @@
import copy
import logging import logging
import re import re
from collections import OrderedDict, defaultdict from collections import OrderedDict, defaultdict
@@ -388,7 +389,7 @@ class OpenAPISchemaGenerator(object):
if method in overrides: if method in overrides:
overrides = overrides[method] overrides = overrides[method]
return overrides return copy.deepcopy(overrides)
def get_path_parameters(self, path, view_cls): def get_path_parameters(self, path, view_cls):
"""Return a list of Parameter instances corresponding to any templated path variables. """Return a list of Parameter instances corresponding to any templated path variables.
@@ -405,8 +406,8 @@ class OpenAPISchemaGenerator(object):
for variable in uritemplate.variables(path): for variable in uritemplate.variables(path):
model, model_field = get_queryset_field(queryset, variable) model, model_field = get_queryset_field(queryset, variable)
attrs = get_basic_type_info(model_field) or {'type': openapi.TYPE_STRING} attrs = get_basic_type_info(model_field) or {'type': openapi.TYPE_STRING}
if hasattr(view_cls, 'lookup_value_regex') and getattr(view_cls, 'lookup_field', None) == variable: if getattr(view_cls, 'lookup_field', None) == variable and attrs['type'] == openapi.TYPE_STRING:
attrs['pattern'] = view_cls.lookup_value_regex attrs['pattern'] = getattr(view_cls, 'lookup_value_regex', attrs.get('pattern', None))
if model_field and model_field.help_text: if model_field and model_field.help_text:
description = force_text(model_field.help_text) description = force_text(model_field.help_text)
+24 -10
View File
@@ -361,7 +361,10 @@ def get_basic_type_info(field):
else: # pragma: no cover else: # pragma: no cover
return None return None
pattern = find_regex(field) if format in (None, openapi.FORMAT_SLUG) else None pattern = None
if swagger_type == openapi.TYPE_STRING and format in (None, openapi.FORMAT_SLUG):
pattern = find_regex(field)
limits = find_limits(field) limits = find_limits(field)
result = OrderedDict([ result = OrderedDict([
@@ -394,16 +397,27 @@ class ChoiceFieldInspector(FieldInspector):
def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs): def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs):
SwaggerType, ChildSwaggerType = self._get_partial_types(field, swagger_object_type, use_references, **kwargs) SwaggerType, ChildSwaggerType = self._get_partial_types(field, swagger_object_type, use_references, **kwargs)
if isinstance(field, serializers.MultipleChoiceField): if isinstance(field, serializers.ChoiceField):
return SwaggerType( enum_type = openapi.TYPE_STRING
type=openapi.TYPE_ARRAY,
items=ChildSwaggerType( # for ModelSerializer, try to infer the type from the associated model field
type=openapi.TYPE_STRING, serializer = get_parent_serializer(field)
enum=list(field.choices.keys()) if isinstance(serializer, serializers.ModelSerializer):
model = getattr(getattr(serializer, 'Meta'), 'model')
model_field = get_model_field(model, field.source)
if model_field:
enum_type = get_basic_type_info(model_field).get('type', enum_type)
if isinstance(field, serializers.MultipleChoiceField):
return SwaggerType(
type=openapi.TYPE_ARRAY,
items=ChildSwaggerType(
type=enum_type,
enum=list(field.choices.keys())
)
) )
)
elif isinstance(field, serializers.ChoiceField): return SwaggerType(type=enum_type, enum=list(field.choices.keys()))
return SwaggerType(type=openapi.TYPE_STRING, enum=list(field.choices.keys()))
return NotHandled return NotHandled
+1
View File
@@ -396,6 +396,7 @@ class Parameter(SwaggerDict):
self.enum = enum self.enum = enum
self.pattern = pattern self.pattern = pattern
self.items = items self.items = items
self.default = default
self._insert_extras__() self._insert_extras__()
if self['in'] == IN_PATH: if self['in'] == IN_PATH:
# path parameters must always be required # path parameters must always be required
+9 -4
View File
@@ -11,10 +11,15 @@ from rest_framework.views import APIView
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
#: used to forcibly remove the body of a request via :func:`.swagger_auto_schema`
no_body = object()
unset = object() class no_body(object):
"""Used as a sentinel value to forcibly remove the body of a request via :func:`.swagger_auto_schema`."""
pass
class unset(object):
"""Used as a sentinel value for function parameters not set by the caller where ``None`` would be a valid value."""
pass
def swagger_auto_schema(method=None, methods=None, auto_schema=unset, request_body=None, query_serializer=None, def swagger_auto_schema(method=None, methods=None, auto_schema=unset, request_body=None, query_serializer=None,
@@ -33,7 +38,7 @@ def swagger_auto_schema(method=None, methods=None, auto_schema=unset, request_bo
: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, and can be set to ``None`` to prevent this operation from being generated 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 :class:`.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'``.
A Schema or SchemaRef is not valid if this request consumes form-data, because ``form`` and ``body`` parameters A Schema or SchemaRef is not valid if this request consumes form-data, because ``form`` and ``body`` parameters
@@ -0,0 +1,18 @@
# Generated by Django 2.0.1 on 2018-02-26 18:32
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('articles', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='article',
name='article_type',
field=models.PositiveSmallIntegerField(choices=[(1, 'first'), (2, 'second'), (3, 'third'), (7, 'seven'), (8, 'eight')], help_text='IntegerField declared on model with choices=(...) and exposed via ModelSerializer', null=True),
),
]
+4
View File
@@ -8,5 +8,9 @@ class Article(models.Model):
date_created = models.DateTimeField(auto_now_add=True) date_created = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True) date_modified = models.DateTimeField(auto_now=True)
author = models.ForeignKey('auth.User', related_name='articles', on_delete=models.CASCADE) author = models.ForeignKey('auth.User', related_name='articles', on_delete=models.CASCADE)
article_type = models.PositiveSmallIntegerField(
help_text="IntegerField declared on model with choices=(...) and exposed via ModelSerializer",
choices=((1, "first"), (2, "second"), (3, "third"), (7, "seven"), (8, "eight")), null=True
)
cover = models.ImageField(upload_to='article/original/', blank=True) cover = models.ImageField(upload_to='article/original/', blank=True)
+2 -2
View File
@@ -16,7 +16,7 @@ class ArticleSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Article model = Article
fields = ('title', 'author', 'body', 'slug', 'date_created', 'date_modified', fields = ('title', 'author', 'body', 'slug', 'date_created', 'date_modified',
'references', 'uuid', 'cover', 'cover_name') 'references', 'uuid', 'cover', 'cover_name', 'article_type')
read_only_fields = ('date_created', 'date_modified', read_only_fields = ('date_created', 'date_modified',
'references', 'uuid', 'cover_name') 'references', 'uuid', 'cover_name')
lookup_field = 'slug' lookup_field = 'slug'
@@ -31,7 +31,7 @@ class ArticleSerializer(serializers.ModelSerializer):
class ImageUploadSerializer(serializers.Serializer): class ImageUploadSerializer(serializers.Serializer):
what_am_i_doing = serializers.RegexField(regex=r"^69$", help_text="test") what_am_i_doing = serializers.RegexField(regex=r"^69$", help_text="test", default="69")
image_styles = serializers.ListSerializer( image_styles = serializers.ListSerializer(
child=serializers.ChoiceField(choices=['wide', 'tall', 'thumb', 'social']), child=serializers.ChoiceField(choices=['wide', 'tall', 'thumb', 'social']),
help_text="Parameter with Items" help_text="Parameter with Items"
+3
View File
@@ -8,6 +8,9 @@ class TodoViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Todo.objects.all() queryset = Todo.objects.all()
serializer_class = TodoSerializer serializer_class = TodoSerializer
lookup_field = 'id'
lookup_value_regex = '[0-9]+'
class TodoAnotherViewSet(viewsets.ReadOnlyModelViewSet): class TodoAnotherViewSet(viewsets.ReadOnlyModelViewSet):
queryset = TodoAnother.objects.all() queryset = TodoAnother.objects.all()
+12 -1
View File
@@ -198,9 +198,10 @@ paths:
- name: what_am_i_doing - name: what_am_i_doing
in: formData in: formData
description: test description: test
required: true required: false
type: string type: string
pattern: ^69$ pattern: ^69$
default: '69'
- name: image_styles - name: image_styles
in: formData in: formData
description: Parameter with Items description: Parameter with Items
@@ -590,6 +591,16 @@ definitions:
cover_name: cover_name:
type: string type: string
readOnly: true readOnly: true
article_type:
description: IntegerField declared on model with choices=(...) and exposed
via ModelSerializer
type: integer
enum:
- 1
- 2
- 3
- 7
- 8
Project: Project:
required: required:
- projectName - projectName
+34
View File
@@ -2,11 +2,14 @@ import json
from collections import OrderedDict from collections import OrderedDict
import pytest import pytest
from rest_framework import routers, serializers, viewsets
from rest_framework.response import Response
from drf_yasg import codecs, openapi from drf_yasg import codecs, openapi
from drf_yasg.codecs import yaml_sane_load from drf_yasg.codecs import yaml_sane_load
from drf_yasg.errors import SwaggerGenerationError from drf_yasg.errors import SwaggerGenerationError
from drf_yasg.generators import OpenAPISchemaGenerator from drf_yasg.generators import OpenAPISchemaGenerator
from drf_yasg.utils import swagger_auto_schema
def test_schema_is_valid(swagger, codec_yaml): def test_schema_is_valid(swagger, codec_yaml):
@@ -79,3 +82,34 @@ def test_securiy_requirements(swagger_settings, mock_schema_request):
swagger = generator.get_schema(mock_schema_request, public=True) swagger = generator.get_schema(mock_schema_request, public=True)
assert swagger['security'] == [] assert swagger['security'] == []
def test_replaced_serializer():
class DetailSerializer(serializers.Serializer):
detail = serializers.CharField()
class DetailViewSet(viewsets.ViewSet):
serializer_class = DetailSerializer
@swagger_auto_schema(responses={404: openapi.Response("Not found or Not accessible", DetailSerializer)})
def retrieve(self, request, pk=None):
serializer = DetailSerializer({'detail': None})
return Response(serializer.data)
router = routers.DefaultRouter()
router.register(r'details', DetailViewSet, base_name='details')
generator = OpenAPISchemaGenerator(
info=openapi.Info(title="Test generator", default_version="v1"),
version="v2",
url='',
patterns=router.urls
)
for _ in range(3):
swagger = generator.get_schema(None, True)
assert 'Detail' in swagger['definitions']
assert 'detail' in swagger['definitions']['Detail']['properties']
responses = swagger['paths']['/details/{id}/']['get']['responses']
assert '404' in responses
assert responses['404']['schema']['$ref'] == "#/definitions/Detail"