Converting a string representation of query to Django object (Q).

1,223 views
Skip to first unread message

gowthaman ramasamy

unread,
Feb 22, 2012, 4:15:04 PM2/22/12
to django...@googlegroups.com
Hi List,
I am just starting to build an application using Django. And my first attempt outside of procedural PHP and Perl-CGI. I am already loving it so much (and ditched other two already).

I am trying to construct the following query at the end.
Result.objects.filter(Q(analysis__experiment__experiment_code="PyLS24") |Q(analysis__experiment__experiment_code="PyLS40"))

How I do now:
The values are passed from a from(post) using checkboxes (#expcodes = request.POST.getlist('expcode')
). So I get a list of:
expcodes = ['PyLS24', 'PyLS40']
then use the for loop to construct string representation of Q object.
expcodes = ['PyLS24', 'PyLS40']
k=''
c=0
for e in expcodes:
j=e.join(['Q(analysis__experiment__experiment_code="','") '])
if c == 0:
k = j
else:
k='|'.join([k, j])
c = c+1

k in this gives me 'Q(analysis__experiment__experiment_code="PyLS24") |Q(analysis__experiment__experiment_code="PyLS40")  '.
When i use this to query the model as following... Result.objects.filter(k) I get "ValueError: too many values to unpack" error. But, exact string, if I copy paste into Results.object.filter(here) it works. 

When I checked the type, k constructed from for loop is in string format (obviously). But, when I copy paste the pint out of k, it automatically becomes Django's Q object.

Can anyone help me to sort this out. Or is there altogether a better way to do this query. I would really appreciate any help.


Gowthaman






Michael Elkins

unread,
Feb 22, 2012, 4:59:42 PM2/22/12
to django...@googlegroups.com
On Wed, Feb 22, 2012 at 01:15:04PM -0800, gowthaman ramasamy wrote:
>I am trying to construct the following query at the end.
>Result.objects.filter(Q(analysis__experiment__experiment_code="PyLS24")
>|Q(analysis__experiment__experiment_code="PyLS40"))
>
>How I do now:
>The values are passed from a from(post) using checkboxes (#expcodes =
>request.POST.getlist('expcode')
>). So I get a list of:
>expcodes = ['PyLS24', 'PyLS40']
>then use the for loop to construct string representation of Q object.
>expcodes = ['PyLS24', 'PyLS40']
>k=''
>c=0
>for e in expcodes:
>j=e.join(['Q(analysis__experiment__experiment_code="','") '])
>if c == 0:
>k = j
>else:
>k='|'.join([k, j])
>c = c+1
>
>k in this gives me 'Q(analysis__experiment__experiment_code="PyLS24")
>|Q(analysis__experiment__experiment_code="PyLS40") '.
>When i use this to query the model as following... Result.objects.filter(k)I get "ValueError: too many values to unpack" error. But, exact string, if

>I copy paste into Results.object.filter(here) it works.
>
>When I checked the type, k constructed from for loop is in string format
>(obviously). But, when I copy paste the pint out of k, it automatically
>becomes Django's Q object.

The issue is that you can't use a string to generate the Q object
passed to filter(). Instead, you need to build them up in a list,
and then use the bitwise-OR operator. You can either do that in a
loop, or this way:

import operator

q_objs = [ Q(analysis__experiment__experiment_code=code) for code in expcodes ]
arg = reduce(operator.or_, q_objs) # do bitwise-OR of all objects in the list
Results.object.filter(arg)

Matt Schinckel

unread,
Feb 22, 2012, 5:04:37 PM2/22/12
to django...@googlegroups.com
The other option, which should work in your case:

    expcodes = ['...', '...']
    Result.objects.filter(analysis__experiment__experiment_code__in=expcodes)

Q objects are great, but not always needed.

Matt.

gowthaman ramasamy

unread,
Feb 22, 2012, 5:11:46 PM2/22/12
to django...@googlegroups.com
Wonderful! Both of them worked. Very importantly, both answers taught me new things. Thanks Matt. Thanks Michael.

Michael Elkins

unread,
Feb 22, 2012, 5:13:57 PM2/22/12
to django...@googlegroups.com

I agree that this is the better solution since the Q objects are
all testing the same field.

/me not seeing the forest through the trees

gowthaman ramasamy

unread,
Feb 22, 2012, 5:20:40 PM2/22/12
to django...@googlegroups.com
True. But, Michael, your answer actually taught me another cool way i did not know before. So, thanks a bunch for that.
Reply all
Reply to author
Forward
0 new messages