Open wlccgp3 opened 2 years ago
Why hasn't it been merged? Pretty sure somebody has the same problem
I tried your solution but not getting multiple files just blank
drf-yasg==1.21.7
Django==4.2.2
djangorestframework==3.14.0
Not getting the fields on Swagger.
from collections import OrderedDict
from drf_yasg import openapi
from drf_yasg.errors import SwaggerGenerationError
from drf_yasg.inspectors.base import NotHandled
from drf_yasg.inspectors.field import FieldInspector, find_limits, filter_none, SerializerInspector, \
get_serializer_ref_name, get_serializer_class
from rest_framework import serializers
from rest_framework.settings import api_settings as rest_framework_settings
class CustomFileFieldInspector(FieldInspector):
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)
if isinstance(field, serializers.FileField):
# swagger 2.0 does not support specifics about file fields, so ImageFile gets no special treatment
# OpenAPI 3.0 does support it, so a future implementation could handle this better
err = SwaggerGenerationError("FileField is supported only in a formData Parameter or response Schema")
if swagger_object_type == openapi.Schema:
# FileField.to_representation returns URL or file name
result = SwaggerType(type=openapi.TYPE_STRING, read_only=True)
if getattr(field, 'use_url', rest_framework_settings.UPLOADED_FILES_USE_URL):
result.format = openapi.FORMAT_URI
return result
elif swagger_object_type in [openapi.Parameter,openapi.Items]:
param = SwaggerType(type=openapi.TYPE_FILE)
if param['in'] != openapi.IN_FORM:
raise err # pragma: no cover
return param
else:
raise err # pragma: no cover
return NotHandled
class InlineSerializerInspector(SerializerInspector):
"""Provides serializer conversions using :meth:`.FieldInspector.field_to_swagger_object`."""
#: whether to output :class:`.Schema` definitions inline or into the ``definitions`` section
use_definitions = False
def get_schema(self, serializer):
return self.probe_field_inspectors(serializer, openapi.Schema, self.use_definitions)
def add_manual_parameters(self, serializer, parameters):
"""Add/replace parameters from the given list of automatically generated request parameters. This method
is called only when the serializer is converted into a list of parameters for use in a form data request.
:param serializer: serializer instance
:param list[openapi.Parameter] parameters: generated parameters
:return: modified parameters
:rtype: list[openapi.Parameter]
"""
return parameters
def get_request_parameters(self, serializer, in_):
fields = getattr(serializer, 'fields', {})
parameters = [
self.probe_field_inspectors(
value, openapi.Parameter, self.use_definitions,
name=self.get_parameter_name(key), in_=in_
)
for key, value
in fields.items()
if not getattr(value, 'read_only', False)
]
return self.add_manual_parameters(serializer, parameters)
def get_property_name(self, field_name):
return field_name
def get_parameter_name(self, field_name):
return field_name
def get_serializer_ref_name(self, serializer):
return get_serializer_ref_name(serializer)
def _has_ref_name(self, serializer):
serializer_meta = getattr(serializer, 'Meta', None)
return hasattr(serializer_meta, 'ref_name')
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)
if isinstance(field, (serializers.ListSerializer, serializers.ListField)):
child_schema = self.probe_field_inspectors(field.child, ChildSwaggerType, use_references,
**kwargs) # add kwargs
limits = find_limits(field) or {}
return SwaggerType(
type=openapi.TYPE_ARRAY,
items=child_schema,
**limits
)
elif isinstance(field, serializers.Serializer):
if swagger_object_type != openapi.Schema:
raise SwaggerGenerationError("cannot instantiate nested serializer as " + swagger_object_type.__name__)
ref_name = self.get_serializer_ref_name(field)
def make_schema_definition(serializer=field):
properties = OrderedDict()
required = []
for property_name, child in serializer.fields.items():
property_name = self.get_property_name(property_name)
prop_kwargs = {
'read_only': bool(child.read_only) or None
}
prop_kwargs = filter_none(prop_kwargs)
child_schema = self.probe_field_inspectors(
child, ChildSwaggerType, use_references, **prop_kwargs
)
properties[property_name] = child_schema
if child.required and not getattr(child_schema, 'read_only', False):
required.append(property_name)
result = SwaggerType(
# the title is derived from the field name and is better to
# be omitted from models
use_field_title=False,
type=openapi.TYPE_OBJECT,
properties=properties,
required=required or None,
)
setattr(result, '_NP_serializer', get_serializer_class(serializer))
return result
if not ref_name or not use_references:
return make_schema_definition()
definitions = self.components.with_scope(openapi.SCHEMA_DEFINITIONS)
actual_schema = definitions.setdefault(ref_name, make_schema_definition)
actual_schema._remove_read_only()
actual_serializer = getattr(actual_schema, '_NP_serializer', None)
this_serializer = get_serializer_class(field)
if actual_serializer and actual_serializer != this_serializer:
explicit_refs = self._has_ref_name(actual_serializer) and self._has_ref_name(this_serializer)
if not explicit_refs:
raise SwaggerGenerationError(
"Schema for %s would override distinct serializer %s because they implicitly share the same "
"ref_name; explicitly set the ref_name attribute on both serializers' Meta classes"
% (actual_serializer, this_serializer))
return openapi.SchemaRef(definitions, ref_name)
return NotHandled
class ReferencingSerializerInspector(InlineSerializerInspector):
use_definitions = True
This is not supported on Newer versions.
Waiting for OpenAPI 3.0
Can you please help on this right now ?
@wlccgp3
@psunny28 your should set something like this
change parser_classes
parser_classes=[MultiPartParser]
serializer
@swagger_auto_schema(
request_body=serializers.UploadSerializer,
)
class UploadSerializer(serializers.Serializer):
files = serializers.ListField(
child=serializers.ImageField(max_length=100000,
allow_empty_file=False,
use_url=False)
)
Bug Report
ListField(chield=ImageField) can not use
Description
SwaggerGenerationError: FileField is supported only in a formData Parameter or response Schema
my solution, and it's work
My Environment