Closed akakakakakaa closed 3 years ago
Judging from a quick look at their code, I don't think this is something that can or should be fixed on our side. drf-yasg will need to be adapted for this.
In general for all drf-yasg issues, I think the most productive solution would be for someone to contribute support to drf-yasg -- there's only so much I can do to imitate the behaviour drf-yasg expects.
You can probably workaround this by explicitly declaring the serializer, btw:
class JobInfoSerializer(DataclassSerializer):
class Meta:
dataclass = JobInfo
class JobInfoGetResponseSerializer(DataclassSerializer):
jobs = JobInfoSerializer(many=True)
class Meta:
dataclass = JobInfos
Hi @oxan
I am sorry if it is not the right place to add this question/information, but it seemed related so I thought of adding it here.
I have a similar issue as described by @akakakakakaa .
I have multiple endpoints using the DataclassSerializer which then generates the wrong information on swagger due to the #definitions generated in the swagger file. The consequence is that every place that DataclassSerializer was used to create a Serializer of a nested dataclass refers to the wrong documentation
Code:
@dataclass
class PolicyEntity:
id: int
...
@dataclass
class Pagination:
page_count: int
page_number: int
total: int
@dataclass
class ListPolicies:
policies: List[PolicyEntity]
pagination: Pagination
class ListPoliciesOutput(DataclassSerializer):
class Meta:
dataclass = ListPolicies
I made this change to make this change and it kind of fixed my issue:
class MyDataclassSerializer(DataclassSerializer):
def build_dataclass_field(self, field_name: str, type_info: TypeInfo) -> SerializerFieldDefinition:
"""
Create fields for dataclasses.
"""
try:
field_class = field_utils.lookup_type_in_mapping(self.serializer_field_mapping, type_info.base_type)
except KeyError:
# Decide between full name with module or only class name
# serializer_field_name = type_info.base_type.__name__
serializer_field_name = f"{type_info.base_type.__module__}.{type_info.base_type.__name__}"
field_class = type(serializer_field_name, (DataclassSerializer,), {})
self.serializer_field_mapping[serializer_field_name] = field_class
field_kwargs = {'dataclass': type_info.base_type,
'many': type_info.is_many}
return field_class, field_kwargs
class ListPoliciesOutput(MyDataclassSerializer):
class Meta:
dataclass = ListPolicies
I thought of sharing the solution I found here. Maybe @oxan decides that it makes sense for the project or if @akakakakakaa wants to use the solution. The solution above is not fully tested yet. I have made it very recently.
As I said before, this is not something that can be fixed from our side. Either somebody needs to contribute support to drf-yasg, or you need to declare the serializers for your nested classes explicitly.
My project moved from drf-yasg to drf-spectacular some time ago. With drf-spectacular, you can define an extension to get the dataclass name:
class OpenApiDataclassSerializerExtensions(OpenApiSerializerExtension):
target_class = "rest_framework_dataclasses.serializers.DataclassSerializer"
match_subclasses = True
priority = 1
def get_name(self) -> str:
return self.target.dataclass_definition.dataclass_type.__name__
@oxan I saw your response, however, I have accidentally posted an incomplete comment. I have updated it.
I just wanted to share what I have done so far just in case you want to change the project to a similar solution or in case @akakakakakaa wants to use the solution.
@intgr Thank you for your comment. I have been meaning to try drf-spectacular, I just haven't had time. What was the reason why you changed from drf-yasg to drf-spectacular?
Thank for your response @oxan
The immediate reason for switching to drf-spectacular was because we needed some OpenAPI 3 features. drf-yasg only supports OpenAPI 2. I don't think there were any downsides to migrating.
Thank you @intgr
Environment
Problem
DataclassSerializer shows Dataclass name appears as "Dataclass" string instead of class name.
According to issue #14, it seems that even nested fields have proper names in the openapi format.