aejsi5
aejsi5

Reputation: 147

Django Q Filter - Too many Values to unpack

I want to dynamicly create some filter criteria depending on the url query params. For this I created a nested Django Q-Object which looks like:

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

Now I want to pass this Q object to Model-Filter

Eort.objects.filter(query)

Thereby I get a 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

Does anybody know how to solve this problem?

This is how I created the 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)

Upvotes: 1

Views: 344

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477240

You should not work with ={2}. A Q object is not a string of the form foo=bar, it is in essence a 2-tuple with as first element a string that is the "key" which is the field and optionally some lookups, and as second element a value, but that value can be a string, datetime object, etc. You thus construct the Q object with:

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)

Upvotes: 1

Related Questions