Apply to_representation on choices

Fixes #340
master
Cristi Vijdea 2019-04-01 02:57:00 +03:00
parent 86c1675c58
commit 7bb4700003
2 changed files with 32 additions and 8 deletions

View File

@ -13,7 +13,9 @@ from rest_framework.settings import api_settings as rest_framework_settings
from .. import openapi from .. import openapi
from ..errors import SwaggerGenerationError from ..errors import SwaggerGenerationError
from ..utils import decimal_as_float, filter_none, get_serializer_class, get_serializer_ref_name from ..utils import (
decimal_as_float, field_value_to_representation, filter_none, get_serializer_class, get_serializer_ref_name
)
from .base import FieldInspector, NotHandled, SerializerInspector, call_view_method from .base import FieldInspector, NotHandled, SerializerInspector, call_view_method
try: try:
@ -635,7 +637,14 @@ class ChoiceFieldInspector(FieldInspector):
if isinstance(field, serializers.ChoiceField): if isinstance(field, serializers.ChoiceField):
enum_type = openapi.TYPE_STRING enum_type = openapi.TYPE_STRING
enum_values = list(field.choices.keys()) enum_values = []
for choice in field.choices.keys():
if isinstance(field, serializers.MultipleChoiceField):
choice = field_value_to_representation(field, [choice])[0]
else:
choice = field_value_to_representation(field, choice)
enum_values.append(choice)
# for ModelSerializer, try to infer the type from the associated model field # for ModelSerializer, try to infer the type from the associated model field
serializer = get_parent_serializer(field) serializer = get_parent_serializer(field)

View File

@ -2,6 +2,7 @@ import inspect
import logging import logging
import sys import sys
from collections import OrderedDict from collections import OrderedDict
from decimal import Decimal
from django.db import models from django.db import models
from django.utils.encoding import force_text from django.utils.encoding import force_text
@ -441,6 +442,25 @@ def force_real_str(s, encoding='utf-8', strings_only=False, errors='strict'):
return s return s
def field_value_to_representation(field, value):
"""Convert a python value related to a field (default, choices, etc.) into its OpenAPI-compatible representation.
:param serializers.Field field: field associated with the value
:param obj value: value
:return: the converted value
"""
value = field.to_representation(value)
if isinstance(value, Decimal):
if decimal_as_float(field):
value = float(value)
else:
value = str(value)
# JSON roundtrip ensures that the value is valid JSON;
# for example, sets and tuples get transformed into lists
return json.loads(json.dumps(value, cls=encoders.JSONEncoder))
def get_field_default(field): def get_field_default(field):
""" """
Get the default value for a field, converted to a JSON-compatible value while properly handling callables. Get the default value for a field, converted to a JSON-compatible value while properly handling callables.
@ -462,12 +482,7 @@ def get_field_default(field):
if default is not serializers.empty and default is not None: if default is not serializers.empty and default is not None:
try: try:
default = field.to_representation(default) default = field_value_to_representation(field, default)
# JSON roundtrip ensures that the value is valid JSON;
# for example, sets and tuples get transformed into lists
default = json.loads(json.dumps(default, cls=encoders.JSONEncoder))
if decimal_as_float(field):
default = float(default)
except Exception: # pragma: no cover except Exception: # pragma: no cover
logger.warning("'default' on schema for %s will not be set because " logger.warning("'default' on schema for %s will not be set because "
"to_representation raised an exception", field, exc_info=True) "to_representation raised an exception", field, exc_info=True)