Django视图集用Q对象查询报错:TypeError无法解包MatchAll对象
问题:Django视图集使用Q对象多条件查询触发TypeError
在Django视图集中使用Q对象进行多条件OR查询时触发TypeError: cannot unpack non-iterable MatchAll object,但相同逻辑在管理命令文件中运行正常;单条件普通filter查询可正常执行。
视图代码
@permission_classes((AllowAny,)) class ClipartViewSet(viewsets.GenericViewSet): serializer_class = ClipartSerializer queryset = Clipart.objects.filter(is_active=True).all() def list(self, request, **kwargs): # Some extra logic # qs = Clipart.objects.filter(name="Apes") # 此代码可正常运行 qs = Clipart.objects.filter(Q(name="Apes") | Q(name="Dog")) # 此代码触发错误 print(qs) return super(ClipartViewSet, self).list(self, request, **kwargs)
错误信息
Internal Server Error: /api/s/configurator/cliparts backend_1 | Traceback (most recent call last): backend_1 | File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 47, in inner backend_1 | response = get_response(request) backend_1 | File "/usr/local/lib/python3.7/site-packages/django/core/handlers/base.py", line 181, in _get_response backend_1 | response = wrapped_callback(request, *callback_args, **callback_kwargs) backend_1 | File "/usr/local/lib/python3.7/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view backend_1 | return view_func(*args, **kwargs) backend_1 | File "/usr/local/lib/python3.7/site-packages/rest_framework/viewsets.py", line 125, in view backend_1 | return self.dispatch(request, *args, **kwargs) backend_1 | File "/usr/local/lib/python3.7/site-packages/rest_framework/views.py", line 509, in dispatch backend_1 | response = self.handle_exception(exc) backend_1 | File "/usr/local/lib/python3.7/site-packages/rest_framework/views.py", line 469, in handle_exception backend_1 | self.raise_uncaught_exception(exc) backend_1 | File "/usr/local/lib/python3.7/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception backend_1 | raise exc backend_1 | File "/usr/local/lib/python3.7/site-packages/rest_framework/views.py", line 506, in dispatch backend_1 | response = handler(request, *args, **kwargs) backend_1 | File "/backend/mycomp/apps/ecommerce/configurator/views/design_views.py", line 109, in list backend_1 | qs = Clipart.objects.filter(Q(name="Apes") | Q(name="Dog")) # This line will show error backend_1 | File "/usr/local/lib/python3.7/site-packages/django/db/models/manager.py", line 85, in manager_method backend_1 | return getattr(self.get_queryset(), name)(*args, **kwargs) backend_1 | File "/usr/local/lib/python3.7/site-packages/safedelete/queryset.py", line 72, in filter backend_1 | return super(SafeDeleteQueryset, queryset).filter(*args, **kwargs) backend_1 | File "/usr/local/lib/python3.7/site-packages/django/db/models/query.py", line 941, in filter backend_1 | return self._filter_or_exclude(False, args, kwargs) backend_1 | File "/usr/local/lib/python3.7/site-packages/django/db/models/query.py", line 961, in _filter_or_exclude backend_1 | clone._filter_or_exclude_inplace(negate, args, kwargs) backend_1 | File "/usr/local/lib/python3.7/site-packages/django/db/models/query.py", line 968, in _filter_or_exclude_inplace backend_1 | self._query.add_q(Q(*args, **kwargs)) backend_1 | File "/usr/local/lib/python3.7/site-packages/django/db/models/sql/query.py", line 1391, in add_q backend_1 | clause, _ = self._add_q(q_object, self.used_aliases) backend_1 | File "/usr/local/lib/python3.7/site-packages/django/db/models/sql/query.py", line 1413, in _add_q backend_1 | split_subq=split_subq, check_filterable=check_filterable, backend_1 | File "/usr/local/lib/python3.7/site-packages/django/db/models/sql/query.py", line 1281, in build_filter backend_1 | arg, value = filter_expr backend_1 | TypeError: cannot unpack non-iterable MatchAll object
解决方案
- 升级django-safedelete库:错误栈显示问题出在
safedelete的QuerySet扩展中,旧版本的该库与Django的Q对象组合查询存在兼容性bug。升级到最新稳定版本即可解决。 - 修正视图逻辑:当前代码仅定义了
qs但未替换视图的queryset属性,调用super().list()时仍会使用初始的queryset。正确写法:def list(self, request, **kwargs): self.queryset = Clipart.objects.filter(Q(name="Apes") | Q(name="Dog")) return super().list(request, **kwargs) - 临时替代方案:如果暂时无法升级库,可用
__in查询替代Q对象的OR逻辑,效果一致:self.queryset = Clipart.objects.filter(name__in=["Apes", "Dog"])
内容的提问来源于stack exchange,提问作者Arun SS
相关产品推荐
相关产品推荐

