В итоге я смог это сделать, хотя, возможно, это не самое элегантное решение, но оно действительно работает.
Мой drf имеет собственный формат меток приложения, поэтому все мои приложения находятся в папке, идавайте назовем эту папку apps
.
В моем вопросе для сериализатора мы можем заменить Serializer4ModelA
в секции properties
в openapi.Schema
пользовательской функцией, скажем, get_serializer(Serializer4ModelA())
.
Таким образом, моя идея состояла в том, чтобы в принципе создать схему самостоятельно, автоматически получая информацию и автоматически создавая словарь properties
.Это очень забавно, но полезно для меня, потому что в моей документации я также хочу передать сериализаторы для Dynamodb, поэтому я сделал очень похожую функцию для сериализаторов Dynamodb.
Я только что сделал это, и это работает,но, очевидно, требуется больше внимания, чтобы охватить все поля в field mapping
, лучше иметь дело с SerializerMethodFields
.
Но тем не менее, это решение, которое работает, но не является общим, твики и прочее придетсябыть сделано в зависимости от вашего конкретного проекта.
Я реализовал функцию примерно следующим образом:
from drf_yasg import openapi
from drf_yasg.inspectors import SwaggerAutoSchema
from drf_yasg.utils import swagger_auto_schema
from drf_yasg.inspectors import FieldInspector
from drf_yasg.utils import swagger_serializer_method
import rest_framework
rest_framework_openapi_field_mapping = {
"ListField": openapi.TYPE_ARRAY,
"CharField": openapi.TYPE_STRING,
"BooleanField": openapi.TYPE_BOOLEAN,
"FloatField": openapi.TYPE_NUMBER,
"DateTimeField": openapi.TYPE_STRING,
"IntegerField": openapi.TYPE_INTEGER,
"SerializerMethodField": openapi.TYPE_STRING
}
def parse_rest_framework_field(field):
rest_framework_field_type = field.split("(")[0]
openapi_field_type =
rest_framework_openapi_field_mapping[rest_framework_field_type]
if "help_text=" in field:
field_description = field.split("help_text='")[-1].split("'")[0]
else:
field_description = None
return openapi.Schema(type=openapi_field_type, description=field_description)
def parse_serializer(serializer):
properties = {}
for k,v in serializer.get_fields().items():
if v.__module__ == "rest_framework.fields":
properties[k] = parse_rest_framework_field(str(v))
elif v.__module__.startswith("apps."):
serializer = str(v).strip().split("(")[0]
exec(f"from {v.__module__} import {serializer}")
eval_serializer = eval(f"{serializer}()")
properties[k] = openapi.Schema(type=openapi.TYPE_OBJECT, properties=parse_serializer(eval_serializer))
else:
pass
return properties
def get_serializer(serializer, description):
""" Needs to return openapi.Schema() """
properties = parse_serializer(serializer)
return_openapi_schema = openapi.Schema( type=openapi.TYPE_OBJECT, properties=properties, description=description)
return return_openapi_schema