views:

36

answers:

2

Hello there,

I came across this blog entry which describes an elegant way of handling results returned from a ChoiceField to a view using a list comprehension technique - one that eliminates empty keys/values without all the intermediate data structures. This particular approach doesn't seem to work for MultipeChoiceFields, though. Is there a similar way one might approach those? (If, for example, the bedroom and bathrooms fields in the following example returned multiple values).

The code is as follows:

if search_form.is_valid():
            searchdict = search_form.cleaned_data
            # It's easier to store a dict of the possible lookups we want, where
            # the values are the keyword arguments for the actual query.
            qdict = { 'city': 'city__icontains',
                    'zip_code': 'zip_code',
                    'property_type': 'property_type_code',
                    'county': 'county__icontains',
                    'minimum_price': 'sale_price__gte',
                    'maximum_price': 'sale_price__lte',
                    'bedrooms': 'bedrooms__gte',
                    'bathrooms': 'baths_total__gte'}
            # Then we can do this all in one step instead of needing to call
            # 'filter' and deal with intermediate data structures.
            q_objs = [Q(**{qdict[k]: searchdict[k]}) for k in qdict.keys() if searchdict.get(k, None)]

Thank you very much...this is an awesome community.

A: 

You might be looking for the IN field lookup like this:

'bathrooms': 'baths_total__in',
stefanw
That won't work since it only retrieves the first item from the dictionary.
WoLpH
I don't see where this should occur. searchdict[k] will be a list.
stefanw
It would occur With a multiplechoicefield, as specified in the topic.
WoLpH
+1  A: 

Hmm... tricky one, the problem is that you only want that specific case to work as multivalued so you can't use the "normal" approach of adding the filters.

Atleast... I'm assuming that if someone selects multiple bathrooms that it would be either instead of both.

This is too much for a one liner I think, but it can work ;)

import operator

create_qs = lambda k, vs: reduce(operator.or_, [Q(**{k: v}) for v in vs])
q_objs = [create_qs(k, searchdict.getlist(k)) for k in qdict.keys() if k in searchdict]
WoLpH