Django项目无法调取swagger.json接口数据
在 Django REST Framework (DRF) 项目中,Swagger (drf-yasg
) 解析 get_queryset()
时,如果 get_queryset()
返回 list
而不是 QuerySet
,会导致 AttributeError: 'list' object has no attribute 'model'
错误。本文记录该问题的调试过程及最终解决方案。
Traceback (most recent call last):
File "G:\MyGitProject\venv\dv3admin\lib\site-packages\rest_framework\views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "G:\MyGitProject\venv\dv3admin\lib\site-packages\drf_yasg\views.py", line 96, in get
schema = generator.get_schema(request, self.public)
File "G:\MyGitProject\MyTools\MyToolsBak\MyToolsBak-HostServer\dvadmin\utils\swagger.py", line 39, in get_schema
swagger = super().get_schema(request, public)
File "G:\MyGitProject\venv\dv3admin\lib\site-packages\drf_yasg\generators.py", line 276, in get_schema
paths, prefix = self.get_paths(endpoints, components, request, public)
File "G:\MyGitProject\venv\dv3admin\lib\site-packages\drf_yasg\generators.py", line 482, in get_paths
operation = self.get_operation(view, path, prefix, method, components, request)
File "G:\MyGitProject\venv\dv3admin\lib\site-packages\drf_yasg\generators.py", line 524, in get_operation
operation = view_inspector.get_operation(operation_keys)
File "G:\MyGitProject\venv\dv3admin\lib\site-packages\drf_yasg\inspectors\view.py", line 33, in get_operation
query = self.get_query_parameters()
File "G:\MyGitProject\venv\dv3admin\lib\site-packages\drf_yasg\inspectors\view.py", line 293, in get_query_parameters
natural_parameters = self.get_filter_parameters() + self.get_pagination_parameters()
File "G:\MyGitProject\venv\dv3admin\lib\site-packages\drf_yasg\inspectors\base.py", line 409, in get_filter_parameters
fields += self.probe_inspectors(self.filter_inspectors, 'get_filter_parameters', filter_backend()) or []
File "G:\MyGitProject\venv\dv3admin\lib\site-packages\drf_yasg\inspectors\base.py", line 110, in probe_inspectors
result = method(obj, **kwargs)
File "G:\MyGitProject\venv\dv3admin\lib\site-packages\drf_yasg\inspectors\query.py", line 42, in get_filter_parameters
return list(map(self.param_to_schema, filter_backend.get_schema_operation_parameters(self.view)))
File "G:\MyGitProject\venv\dv3admin\lib\site-packages\django_filters\rest_framework\backends.py", line 146, in get_schema_operation_parameters
filterset_class = self.get_filterset_class(view, queryset)
File "G:\MyGitProject\venv\dv3admin\lib\site-packages\django_filters\rest_framework\backends.py", line 40, in get_filterset_class
queryset.model, filterset_model
AttributeError: 'list' object has no attribute 'model'
该错误发生在 drf-yasg
解析 Swagger API 文档时,表明某个 ViewSet
的 get_queryset()
方法返回了 list
,而 Swagger 期望 QuerySet
。
错误代码示例
# ❌ 错误示例:返回 list
def get_queryset(self):
fixed_ids = [11, 12]
fixed_records = ArticleTag.objects.filter(id__in=fixed_ids)
remaining_records = ArticleTag.objects.exclude(id__in=fixed_ids)
random_records = remaining_records.order_by('?')[:5]
queryset = list(fixed_records) + list(random_records) # ❌ 把 QuerySet 变成了 list
return queryset # ❌ Swagger 解析失败
比如我的代码里是这样的,仔细看发布时发现问题了。
def get_queryset(self):
# 获取固定的记录
fixed_ids = [11, 12]
fixed_records = ArticleTag.objects.filter(id__in=fixed_ids)
# 获取其余的记录
remaining_records = ArticleTag.objects.exclude(id__in=fixed_ids)
# 随机选择5个记录
random_records = remaining_records.order_by('?')[:5]
# 合并固定记录和随机记录
queryset = list(fixed_records) + list(random_records)
return queryset
确保 get_queryset()
返回 QuerySet
使用 union()
合并多个 QuerySet
# ✅ 正确示例:使用 `union()`
def get_queryset(self):
fixed_ids = [11, 12]
fixed_records = ArticleTag.objects.filter(id__in=fixed_ids)
remaining_records = ArticleTag.objects.exclude(id__in=fixed_ids)
random_records = remaining_records.order_by('?')[:5]
queryset = fixed_records.union(random_records) # ✅ 确保返回 QuerySet
return queryset
✅ union()
组合两个 QuerySet
,避免 list
类型错误。
如何调试 get_queryset()
返回类型
手动打印 get_queryset()
返回值类型
# 在所有 ViewSet 里加入调试代码
import logging
logger = logging.getLogger(__name__)
def get_queryset(self):
queryset = ArticleTag.objects.all()
logger.debug(f"🔍 调试: {self.__class__.__name__}.get_queryset() 返回 {type(queryset)}")
return queryset
执行 Swagger 请求 (http://127.0.0.1:8000/swagger.json
) 后,检查 django.log
里打印的 queryset
类型。
在 Django Shell 里手动测试
python manage.py shell
然后执行:
from app.views import ExampleViewSet
view = ExampleViewSet()
print(type(view.get_queryset())) # 如果输出 <class 'list'>,说明有问题
如果 get_queryset()
返回 list
,则需要修改代码,确保它返回 QuerySet
。
✅ 其他常见问题 & 解决方案
问题 | 错误代码 | 解决方案 |
---|---|---|
get_queryset() 直接返回了 list | return list(queryset) | 改成 QuerySet ,如 queryset.union(another_queryset) |
.values() 或 .values_list(..., flat=True) 可能导致 list | queryset.values('field') | 改成 .values_list('field', flat=True) |
解析 Swagger 时找不到出错的 API | swagger.py 解析失败 | 在 swagger.py 里 logger.error("Swagger 解析失败: {e}") |
Django Shell 运行 view.get_queryset() 发现返回 list | python manage.py shell | 修复 get_queryset() ,确保返回 QuerySet |
总结
如何防止 AttributeError: 'list' object has no attribute 'model'
错误?
1️⃣ 确保 get_queryset()
返回 QuerySet
,而不是 list
2️⃣ 使用 union()
代替 list + list
3️⃣ 检查 .values()
是否返回 list
,改成 .values_list(..., flat=True)
4️⃣ 用 print(type(queryset))
或 Django Shell 调试
🚀 这样,Swagger 解析不会再出错,API 文档可以正常生成! 🎯