【问题标题】:Django Q Filter - Too many Values to unpackDjango Q 过滤器 - 太多值无法解包
【发布时间】:2021-07-01 04:44:26
【问题描述】:

我想根据 url 查询参数动态创建一些过滤条件。 为此,我创建了一个嵌套的 Django Q-Object,如下所示:

query = <Q: (AND: (OR: region=30, region=39), name__endswith=Hannover, zip_code=30165)>

现在我想将这个 Q 对象传递给 Model-Filter

Eort.objects.filter(query)

因此我得到一个 ValueError : too many values to unpack (expected 2)

Traceback (most recent call last):
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response     
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view    
    return view_func(*args, **kwargs)
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\views\generic\base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\rest_framework\views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\rest_framework\views.py", line 469, in handle_exception       
    self.raise_uncaught_exception(exc)
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
    raise exc
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\rest_framework\views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "C:\Users\felix\Documents\WZO\WZO\WZO_App\views.py", line 47, in get
    log.debug(Eort.objects.filter(eq))
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\db\models\manager.py", line 85, in manager_method      
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\db\models\query.py", line 942, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\db\models\query.py", line 962, in _filter_or_exclude   
    clone._filter_or_exclude_inplace(negate, *args, **kwargs)
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\db\models\query.py", line 969, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\db\models\sql\query.py", line 1358, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\db\models\sql\query.py", line 1380, in _add_q
    split_subq=split_subq, check_filterable=check_filterable,
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\db\models\sql\query.py", line 1244, in build_filter    
    check_filterable=check_filterable,
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\db\models\sql\query.py", line 1380, in _add_q
    split_subq=split_subq, check_filterable=check_filterable,
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\db\models\sql\query.py", line 1244, in build_filter    
    check_filterable=check_filterable,
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\db\models\sql\query.py", line 1380, in _add_q
    split_subq=split_subq, check_filterable=check_filterable,
  File "C:\Users\felix\Documents\WZO\myenv\lib\site-packages\django\db\models\sql\query.py", line 1255, in build_filter    
    arg, value = filter_expr

有人知道如何解决这个问题吗?

这就是我创建 Q-Object 的方式:

def or_operator(self, key, qlist):
        if qlist:
            result = Q()
            result.connector = Q.OR
            for i in qlist:
                if i == '':
                    continue
                if i[0] == '%' and i[-1] == '%':
                    result.add(Q('{0}__{1}={2}'.format(key, 'contains', i[1:-1])), Q.OR)
                elif i[0] == '%' and not i[-1] == '%':
                    result.add(Q('{0}__{1}={2}'.format(key, 'startswith', i[1:])), Q.OR)
                elif not i[0] == '%' and i[-1] == '%':
                    result.add(Q('{0}__{1}={2}'.format(key, 'endswith', i[:-1])), Q.OR)
                else:
                    result.add(Q('{0}={1}'.format(key, i)), Q.OR)
            return result 

query = Q()
query.connector = Q.AND
for key in params:
    if key in ['lat', 'lng', 'name', 'street', 'zip_code', 'city', 'region']:
        val = params.get(key, None).split(',')
        query.add(self.or_operator(key, val),Q.AND)

【问题讨论】:

  • 你是如何构造这个Q对象的?
  • 添加构造函数

标签: python django django-models


【解决方案1】:

您不应该使用={2}Q 对象 不是 foo=bar 形式的字符串,它本质上是一个 2 元组,第一个元素是作为“键”的字符串,它是字段,也可以选择一些查找,并将值作为第二个元素,但该值可以是字符串、datetime 对象等。因此,您可以使用以下命令构造 Q 对象:

if i[0] == '%' and i[-1] == '%':
    result.add(Q((f'{key}__contains', i[1:-1])), Q.OR)
elif i[0] == '%' and not i[-1] == '%':
    result.add(Q((f'{key}__startswith', i[1:])), Q.OR)
elif not i[0] == '%' and i[-1] == '%':
    result.add(Q((f'{key}__endswith', i[:-1])), Q.OR)
else:
    result.add(Q((key, i)), Q.OR)

【讨论】:

  • Q 对象看起来有点不同。
  • @aejsi5:您是否将值包装到 2 元组中?
  • @aejsi5:根据输出,您写的是Q(key, i),而不是Q((key, i))。您需要将值包装在 2 元组中,而不是将它们作为单独的项目传递。
猜你喜欢
  • 1970-01-01
  • 2016-01-16
  • 2019-03-28
  • 1970-01-01
  • 2021-10-01
  • 2018-07-01
  • 2021-02-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多