From 23ebba420734d9760d2e60d4c3b057d7accc8996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristi=20V=C3=AEjdea?= Date: Wed, 8 Aug 2018 01:41:54 +0300 Subject: [PATCH] Rename swagger_serializer_method parameter and update docs --- docs/custom_spec.rst | 58 +++++++++++-------- src/drf_yasg/inspectors/field.py | 4 +- src/drf_yasg/utils.py | 6 +- .../method_serializers_without_typing.py | 14 ++--- testproj/users/serializers.py | 8 +-- 5 files changed, 49 insertions(+), 41 deletions(-) diff --git a/docs/custom_spec.rst b/docs/custom_spec.rst index 418ce9c..1f8fef0 100644 --- a/docs/custom_spec.rst +++ b/docs/custom_spec.rst @@ -159,44 +159,52 @@ Where you can use the :func:`@swagger_auto_schema <.swagger_auto_schema>` decora Support for SerializerMethodField ********************************* -Schema generation of ``serializers.SerializerMethodField`` supported in two ways: +Schema generation of ``serializers.SerializerMethodField`` is supported in two ways: -1) The decorator ``swagger_serializer_method(serializer)`` for the use case where the serializer method - is using a serializer. e.g.: +1) The :func:`swagger_serializer_method <.swagger_serializer_method>` decorator for the use case where the serializer + method is using a serializer. e.g.: + + .. code-block:: python + + from drf_yasg.utils import swagger_serializer_method + + class OtherStuffSerializer(serializers.Serializer): + foo = serializers.CharField() + + class ParentSerializer(serializers.Serializer): + other_stuff = serializers.SerializerMethodField() + + @swagger_serializer_method(serializer_or_field=OtherStuffSerializer) + def get_other_stuff(self, obj): + return OtherStuffSerializer().data -.. code-block:: python - - from drf_yasg.utils import swagger_serializer_method + Note that the ``serializer_or_field`` parameter can accept either a subclass or an instance of ``serializers.Field``. - class OtherStuffSerializer(serializers.Serializer): - foo = serializers.CharField() +2) For simple cases where the method is returning one of the supported types, `Python 3 type hinting`_ of the + serializer method return value can be used. e.g.: + .. code-block:: python - class ParentSerializer(serializers.Serializer): + class SomeSerializer(serializers.Serializer): + some_number = serializers.SerializerMethodField() - other_stuff = serializers.SerializerMethodField() + def get_some_number(self, obj) -> float: + return 1.0 - @swagger_serializer_method(serializer=OtherStuffSerializer) - def get_other_stuff(self, obj): - return OtherStuffSerializer().data + When return type hinting is not supported, the equivalent ``serializers.Field`` subclass can be used with + :func:`swagger_serializer_method <.swagger_serializer_method>`: + .. code-block:: python -Note that the serializer parameter can be either be a serializer class or instance + class SomeSerializer(serializers.Serializer): + some_number = serializers.SerializerMethodField() + @swagger_serializer_method(serializer_or_field=serializers.FloatField) + def get_some_number(self, obj): + return 1.0 -2) For simple cases where the method is returning one of the supported types, - `Python 3 type hinting`_ of the serializer method return value can be used. e.g.: - - .. code-block:: python - - class SomeSerializer(serializers.Serializer): - - some_number = serializers.SerializerMethodField() - - def get_some_number(self, obj) -> float: - return 1.0 ******************************** Serializer ``Meta`` nested class diff --git a/src/drf_yasg/inspectors/field.py b/src/drf_yasg/inspectors/field.py index 51b4d26..5bd169c 100644 --- a/src/drf_yasg/inspectors/field.py +++ b/src/drf_yasg/inspectors/field.py @@ -459,8 +459,8 @@ def get_basic_type_info_from_hint(hint_class): class SerializerMethodFieldInspector(FieldInspector): - """Provides conversion for SerializerMethodField, optionally using information from the swagger_method_field - decorator + """Provides conversion for SerializerMethodField, optionally using information from the swagger_serializer_method + decorator. """ def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs): diff --git a/src/drf_yasg/utils.py b/src/drf_yasg/utils.py index 7de77df..7a54440 100644 --- a/src/drf_yasg/utils.py +++ b/src/drf_yasg/utils.py @@ -178,18 +178,18 @@ def swagger_auto_schema(method=None, methods=None, auto_schema=unset, request_bo return decorator -def swagger_serializer_method(serializer): +def swagger_serializer_method(serializer_or_field): """ Decorates the method of a serializers.SerializerMethodField to hint as to how Swagger should be generated for this field. - :param serializer: serializer class or instance + :param serializer_or_field: ``Serializer``/``Field`` class or instance :return: """ def decorator(serializer_method): # stash the serializer for SerializerMethodFieldInspector to find - serializer_method._swagger_serializer = serializer + serializer_method._swagger_serializer = serializer_or_field return serializer_method return decorator diff --git a/testproj/users/method_serializers_without_typing.py b/testproj/users/method_serializers_without_typing.py index 81edd86..85df8f6 100644 --- a/testproj/users/method_serializers_without_typing.py +++ b/testproj/users/method_serializers_without_typing.py @@ -22,21 +22,21 @@ class MethodFieldExampleSerializer(serializers.Serializer): hinted_bool = serializers.SerializerMethodField( help_text="the type hint on the method should determine this to be a bool") - @swagger_serializer_method(serializer=serializers.BooleanField) + @swagger_serializer_method(serializer_or_field=serializers.BooleanField) def get_hinted_bool(self, obj): return True hinted_int = serializers.SerializerMethodField( help_text="the type hint on the method should determine this to be an integer") - @swagger_serializer_method(serializer=serializers.IntegerField) + @swagger_serializer_method(serializer_or_field=serializers.IntegerField) def get_hinted_int(self, obj): return 1 hinted_float = serializers.SerializerMethodField( help_text="the type hint on the method should determine this to be a number") - @swagger_serializer_method(serializer=serializers.FloatField) + @swagger_serializer_method(serializer_or_field=serializers.FloatField) def get_hinted_float(self, obj): return 1.0 @@ -44,28 +44,28 @@ class MethodFieldExampleSerializer(serializers.Serializer): help_text="the type hint on the method should determine this to be a decimal") # note that in this case an instance is required since DecimalField has required arguments - @swagger_serializer_method(serializer=serializers.DecimalField(max_digits=6, decimal_places=4)) + @swagger_serializer_method(serializer_or_field=serializers.DecimalField(max_digits=6, decimal_places=4)) def get_hinted_decimal(self, obj): return decimal.Decimal(1) hinted_datetime = serializers.SerializerMethodField( help_text="the type hint on the method should determine this to be a datetime") - @swagger_serializer_method(serializer=serializers.DateTimeField) + @swagger_serializer_method(serializer_or_field=serializers.DateTimeField) def get_hinted_datetime(self, obj): return datetime.datetime.now() hinted_date = serializers.SerializerMethodField( help_text="the type hint on the method should determine this to be a date") - @swagger_serializer_method(serializer=serializers.DateField) + @swagger_serializer_method(serializer_or_field=serializers.DateField) def get_hinted_date(self, obj): return datetime.date.today() hinted_uuid = serializers.SerializerMethodField( help_text="the type hint on the method should determine this to be a uuid") - @swagger_serializer_method(serializer=serializers.UUIDField) + @swagger_serializer_method(serializer_or_field=serializers.UUIDField) def get_hinted_uuid(self, obj): return uuid.uuid4() diff --git a/testproj/users/serializers.py b/testproj/users/serializers.py index c51ec39..8c5dc54 100644 --- a/testproj/users/serializers.py +++ b/testproj/users/serializers.py @@ -26,7 +26,7 @@ class UserSerializerrr(serializers.ModelSerializer): hint_example = MethodFieldExampleSerializer() - @swagger_serializer_method(serializer=OtherStuffSerializer) + @swagger_serializer_method(serializer_or_field=OtherStuffSerializer) def get_other_stuff(self, obj): """ method_field that uses a serializer internally. @@ -41,7 +41,7 @@ class UserSerializerrr(serializers.ModelSerializer): help_text="help text on field is set, so this should appear in swagger" ) - @swagger_serializer_method(serializer=serializers.IntegerField( + @swagger_serializer_method(serializer_or_field=serializers.IntegerField( help_text="decorated instance help_text shouldn't appear in swagger because field has priority")) def get_help_text_example_1(self): """ @@ -52,7 +52,7 @@ class UserSerializerrr(serializers.ModelSerializer): help_text_example_2 = serializers.SerializerMethodField() - @swagger_serializer_method(serializer=serializers.IntegerField( + @swagger_serializer_method(serializer_or_field=serializers.IntegerField( help_text="instance help_text is set, so should appear in swagger")) def get_help_text_example_2(self): """ @@ -63,7 +63,7 @@ class UserSerializerrr(serializers.ModelSerializer): help_text_example_3 = serializers.SerializerMethodField() - @swagger_serializer_method(serializer=serializers.IntegerField()) + @swagger_serializer_method(serializer_or_field=serializers.IntegerField()) def get_help_text_example_3(self): """ docstring is set so should appear in swagger as fallback