Оставлю это здесь, как черновик.
drf-spectacular плохо дружит с SerializerMethodField. Поэтому я написал свой класс поля.
Внимание в коде используетсяmixin_for
classDataSerializerField(Field):"""A serializer for calculated data"""def__new__(cls,serializer:Type["SerializerType"],*args,method_name=None,**kwargs)->"SerializerType":classGetAttributeMixin(mixin_for(Field)):defget_attribute(self,instance):ifself.source_attrs:value=super().get_attribute(instance)else:default_method_name=f"get_{self.field_name}_data"attr_name=method_nameordefault_method_namemethod=getattr(self.parent,attr_name,None)ifnotmethod:raiseAttributeError(f"Method{attr_name} not found in class{type(self.parent).__name__}")value=method(instance)returnvalueclass_name=f'{serializer.__name__.replace("Serializer","")}DataSerializer'list_serializer_class=type("DataListSerializer",(GetAttributeMixin,ListSerializer),{})parent_meta_class=getattr(serializer,"Meta",object)ref_name=class_name+now_as_timestamp_str()meta_class=type("Meta",(parent_meta_class,),{"list_serializer_class":list_serializer_class,"ref_name":ref_name},)data_serializer_class=type(class_name,(GetAttributeMixin,serializer),{"Meta":meta_class})kwargs.setdefault("source","*")kwargs["read_only"]=Truekwargs["required"]=Falsereturndata_serializer_class(**kwargs)
Пример использования:
classParentSerializer(Serializer):serializer_field_object=DataSerializerField(ChildSerializer)serializer_field_list=DataSerializerField(ChildSerializer,many=True)defget_serializer_field_object_data(parent_obj)->ChildObject:returnChildObject()defget_serializer_field_list_data(parent_obj)->list[ChildObject]:return[ChildObject(),ChildObject()]
Аннотацию результатов методов можно не писать, она влияет только на работу линтеров.
Этот же код с SerializerMethodField выглядел бы так
classParentSerializer(Serializer):serializer_field_object=SerializerMethodField()serializer_field_list=SerializerMethodField()defget_serializer_field_object(parent_obj)->ChildSerializer:returnChildSerializer(ChildObject()).datadefget_serializer_field_list(parent_obj)->list[ChildSerializer]:returnChildSerializer([ChildObject(),ChildObject()]).data
Обратите внимание на аннотацию результатов функций. Она нужна для того, чтобы spectacular-swagger мог правильно отобразить схему. При этом аннотация не соответствует реальному типу возвращаемых данных.
Top comments(0)
Subscribe
For further actions, you may consider blocking this person and/orreporting abuse