Reputation: 147
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
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