views:

44

answers:

3

I'm filtering a big number of users based on attributes. For example, they can be filtered by minimum gpa.

So far I've been doing the following to construct my queryset-

('gpa_gt' just means that the gpa property has to be greater than whatever is the query param)

    if len(request.GET) != 0:
        kwargs = {}
        if request.GET['mingpa']:
            kwargs['gpa__gt'] = request.GET['mingpa']
    profiles = BlahUser.objects.filter(**kwargs)

Now, the users have a first school major attribute and a second school major attribute. If I filter by a major, I want the user to show up in the results if his first major OR his second major match any of my selections (I use a multiple select on the filtering). What I have now only works for one major-

    if request.GET.has_key('major'):
            kwargs['major__in'] = request.GET.getlist('major')

I know how to explicitly write out the query, but in my case I'm building it dynamically of sorts, and am stumped at how to do so. Any help appreciated, thanks!

A: 

I'm thinking of this so far- (course being major)

     if request.GET.has_key('course'):
            extra = ['Q(first_course IN ' + request.GET.getlist('course') + ') | Q(second_course IN ' + request.GET.getlist('course') + ')']
            profiles = sumaConnectUser.objects.extra(where=[extra])

'course' is what we call a major. I haven't checked whether the above works but it's a start..

Help? lol

Dpetters
+2  A: 

You inclusively or in Django querysets with the Q object:

Poll.objects.get(
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
    question__startswith='Who')

You can operate on them like variables so you would like something like this:

query = Q( gpa__gt=request.GET['mingpa'] )
if request.GET.has_key('major'):
    query = query | Q( major__in=request.GET.getlist('major') )
profiles = BlahUser.objects.get( query )
Borgar
Dpetters
I may be mistaken but I think your example will include all students with a GPA above the specified minumum and also students that major in any of the specified majors, regardless of GPA, since you are combining your Q objects with 'OR'.
Chris Lawlor
I figured just providing a basic example of inclusive OR + a link to the docs would be enough to get things moving. Didn't really have the patience to go for completeness this time. :-)
Borgar
+1  A: 

Borgar is definitely on the right track, but I think this is a little closer to what you are looking for:

# filter for minimum GPA
gpa_filter = Q( gpa__gt=request.GET['mingpa'] )
major_filter = Q()

if request.GET.has_key('major'):
    majors = request.GET.getlist('major')
    # filter for students with first OR second major in specified majors
    major_filter = Q( first_major__in=majors| Q(second_major__in=majors)

# run filter (these are AND'ed together), so we get students that:
# 1. Have a first or second major in the specified list of majors AND
# 2. Have a GPA above the specified minimum
profiles = BlahUser.objects.get( gpa_filter, major_filter )

Note that you can continue to use profiles as a regular queryset (as in this contrived example):

seniors_matching_request_params = profiles.filter(status='senior')

So, just use Q objects where you need to, then continue to operate on the queryset as normal .

Chris Lawlor