Fix OpenAPI Schema yaml rendering for timedelta (#9007)

* fix OpenAPIRenderer for timedelta

* added test for rendering openapi with timedelta

* fix OpenAPIRenderer for timedelta

* added test for rendering openapi with timedelta

* Removed usage of field.choices that triggered full table load (#8950)

Removed the `{{ field.choices|yesno:",disabled" }}` block because this triggers the loading of full database table worth of objects just to determine whether the multi-select widget should be set as disabled or not.

Since this "disabled" marking feature is not present in the normal select field, then I propose to remove it also from the multi-select.

* Added Deprecation Warnings for CoreAPI (#7519)

* Added Deprecation Warnings for CoreAPI

* Bumped removal to DRF315

* Update rest_framework/__init__.py

* Update rest_framework/filters.py

* Update rest_framework/filters.py

* Update tests/schemas/test_coreapi.py

* Update rest_framework/filters.py

* Update rest_framework/filters.py

* Update tests/schemas/test_coreapi.py

* Update tests/schemas/test_coreapi.py

* Update setup.cfg

* Update rest_framework/pagination.py

---------

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>

* Update copy right timeline

* Fix NamespaceVersioning ignoring DEFAULT_VERSION on non-None namespaces (#7278)

* Fix the case where if the namespace is not None and there's no match,
  NamespaceVersioning always raises NotFound even if DEFAULT_VERSION
  is set or None is in ALLOWED_VERSIONS

* Add test cases

* fix OpenAPIRenderer for timedelta

* added test for rendering openapi with timedelta

* added testcase for rendering yaml with minvalidator for duration field (timedelta)

---------

Co-authored-by: Rizwan Shaikh <rshaikh@ces-ltd.com>
Co-authored-by: Lenno Nagel <lenno@namespace.ee>
Co-authored-by: David Smith <39445562+smithdc1@users.noreply.github.com>
Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
Co-authored-by: Konstantin Kuchkov <konstantin.kuchkov@gmail.com>
This commit is contained in:
rizwanshaikh 2023-06-17 08:48:25 +05:30 committed by GitHub
parent 71f87a5864
commit 9cfa4bd7cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 0 deletions

View File

@ -9,6 +9,7 @@ REST framework also provides an HTML renderer that renders the browsable API.
import base64
import contextlib
import datetime
from urllib import parse
from django import forms
@ -1062,6 +1063,7 @@ class OpenAPIRenderer(BaseRenderer):
def ignore_aliases(self, data):
return True
Dumper.add_representer(SafeString, Dumper.represent_str)
Dumper.add_representer(datetime.timedelta, encoders.CustomScalar.represent_timedelta)
return yaml.dump(data, default_flow_style=False, sort_keys=False, Dumper=Dumper).encode('utf-8')

View File

@ -65,3 +65,14 @@ class JSONEncoder(json.JSONEncoder):
elif hasattr(obj, '__iter__'):
return tuple(item for item in obj)
return super().default(obj)
class CustomScalar:
"""
CustomScalar that knows how to encode timedelta that renderer
can understand.
"""
@classmethod
def represent_timedelta(cls, dumper, data):
value = str(data.total_seconds())
return dumper.represent_scalar('tag:yaml.org,2002:str', value)

View File

@ -1162,6 +1162,31 @@ class TestGenerator(TestCase):
assert b'"openapi": "' in ret
assert b'"default": "0.0"' in ret
def test_schema_rendering_to_yaml(self):
patterns = [
path('example/', views.ExampleGenericAPIView.as_view()),
]
generator = SchemaGenerator(patterns=patterns)
request = create_request('/')
schema = generator.get_schema(request=request)
ret = OpenAPIRenderer().render(schema)
assert b"openapi: " in ret
assert b"default: '0.0'" in ret
def test_schema_rendering_timedelta_to_yaml_with_validator(self):
patterns = [
path('example/', views.ExampleValidatedAPIView.as_view()),
]
generator = SchemaGenerator(patterns=patterns)
request = create_request('/')
schema = generator.get_schema(request=request)
ret = OpenAPIRenderer().render(schema)
assert b"openapi: " in ret
assert b"duration:\n type: string\n minimum: \'10.0\'\n" in ret
def test_schema_with_no_paths(self):
patterns = []
generator = SchemaGenerator(patterns=patterns)

View File

@ -134,6 +134,11 @@ class ExampleValidatedSerializer(serializers.Serializer):
ip4 = serializers.IPAddressField(protocol='ipv4')
ip6 = serializers.IPAddressField(protocol='ipv6')
ip = serializers.IPAddressField()
duration = serializers.DurationField(
validators=(
MinValueValidator(timedelta(seconds=10)),
)
)
class ExampleValidatedAPIView(generics.GenericAPIView):