使用drf-spectacular时出现QuerySet无model属性的AttributeError求助
解决drf-spectacular与rest_framework_mongoengine兼容的AttributeError问题
问题原因
drf-spectacular原本是为Django ORM设计的,它内部会依赖QuerySet的model属性生成API元数据,但rest_framework_mongoengine提供的QuerySet并没有这个属性,所以访问文档端点时会触发AttributeError: 'QuerySet' object has no attribute 'model'错误。
具体解决步骤
1. 自定义MongoEngine QuerySet转换器
创建转换器让drf-spectacular能识别mongoengine的QuerySet,在你的app下新建spectacular_extensions.py文件:
from drf_spectacular.plumbing import ResolvedComponent from rest_framework_mongoengine.queryset import QuerySet from drf_spectacular.settings import spectacular_settings def mongoengine_queryset_converter(serializer, request, path, method): model_cls = serializer.Meta.model component = ResolvedComponent( name=f"{model_cls.__name__}List", type=ResolvedComponent.SERIALIZER, object=serializer, schema=None, ) return { "type": "array", "items": component.ref, } # 注册转换器到spectacular设置 spectacular_settings.SERIALIZER_CONVERTERS[QuerySet] = mongoengine_queryset_converter
然后在项目的settings.py里导入这个文件,确保它在drf-spectacular之前加载:
# settings.py import your_app.spectacular_extensions
2. 显式定义视图的查询集和序列化器
不要依赖视图自动推断queryset,而是重写get_queryset方法,同时明确指定serializer_class:
from rest_framework_mongoengine.viewsets import ModelViewSet from .models import Service from .serializers import ServiceSerializer class ServiceViewSet(ModelViewSet): serializer_class = ServiceSerializer def get_queryset(self): return Service.objects.all()
3. 用extend_schema显式声明视图的请求/响应格式
如果单个视图(比如你的CreateServiceAPI)还是有问题,用drf-spectacular的装饰器直接指定schema:
from rest_framework.generics import CreateAPIView from drf_spectacular.utils import extend_schema from .models import Service from .serializers import ServiceSerializer class CreateServiceAPI(CreateAPIView): serializer_class = ServiceSerializer @extend_schema( request=ServiceSerializer, responses=ServiceSerializer ) def post(self, request, *args, **kwargs): return super().post(request, *args, **kwargs)
4. 调整spectacular配置避免自动检测冲突
在settings.py的SPECTACULAR_SETTINGS中,关闭可能引发问题的自动参数检测:
SPECTACULAR_SETTINGS = { 'TITLE': '你的API名称', 'DESCRIPTION': '基于Django-MongoEngine的API文档', 'VERSION': '1.0.0', 'AUTO_INCLUDE_PARAMETERS': False, }
内容的提问来源于stack exchange,提问作者ammar Yasser
相关产品推荐
相关产品推荐

