1
votes

Well, I've been pulling my hair out over this one for many hours now and figured it's time to seek assistance as I'm not able to find out why this is happening via google searches...

Essentially I'm making a classifieds type application and I need a search form to search the database and filter based on various criteria. I'm using django, haystack and whoosh and I've got it almost working perfectly but I cannot seem to make it filter on Boolean variables. I've successfully got it filtering on the Charfield category and it works perfectly but when I try to add in the filter based on the for_sale Boolean (or any boolean for that matter) it doesn't filter anything and returns the same results as if it were never called (I have checked and it is actually being called).

Anyone have any ideas?

The relevant part of my model:

class Listing(models.Model):
    SALE_CHOICES=((True, 'Items for sale'),
          (False, 'Items wanted'))
    for_sale = models.BooleanField(choices=SALE_CHOICES, default=True)
    CAT_CHOICES = ((WOOD, "Woods"), (BRICKS, "Bricks"), etc)
    category = models.CharField(max_length=6, choices = CAT_CHOICES, default = WOOD)

This is my listing index class:

class ListingIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)
    title = indexes.CharField(model_attr='title')
    text_content = indexes.CharField(model_attr='text_content')
    created = indexes.DateTimeField(model_attr='created')
    url = indexes.CharField(model_attr='url')
    price = indexes.CharField(model_attr='price', null=True)
    city = indexes.CharField(model_attr='city', null=True)
    category = indexes.CharField(model_attr='category')
    for_sale = indexes.BooleanField(model_attr='for_sale', default=True)

def get_model(self):
    return Listing

def index_queryset(self, using=None):
    return self.get_model().objects.filter(expired=False).filter(verified=True)   

My extended SearchForm and SearchView:

class ListingSearchForm(FacetedSearchForm):
    cat = forms.CharField(required=False, widget=forms.Select(choices=get_listings_categories()))
    type = forms.CharField(required=False, widget=forms.HiddenInput)
    for_sale = forms.BooleanField(required=False, widget=forms.Select(choices=get_sale_categories()))

def search(self):
    # First, store the SearchQuerySet received from other processing.
    sqs = super(ListingSearchForm, self).search()

    # Check to see if a category was chosen.
    if self.cleaned_data['cat']:
        sqs = sqs.filter(category=self.cleaned_data['cat'])

    # Check to see if a type was chosen.
    if self.cleaned_data['for_sale']:
        sqs = sqs.filter(for_sale=self.cleaned_data['for_sale'])

    return sqs


class ListingSearchView(SearchView):

    def extra_context(self):
        extra = super(ListingSearchView, self).extra_context()

        extra['post_type'] = self.request.GET.get('type', None)
        extra['cat'] = self.request.GET.get('cat', None)
        extra['for_sale'] = self.request.GET.get('for_sale', None)

        return extra

And finally my listing index text file:

{{ object.title }}
{{ object.text_content }}
{{ object.created }}
{{ object.url }}
{{ object.category }}
{{ object.price }}
{{ object.city }}
{{ object.for_sale }}
2
There are two versions of django-haystack, 1.x and 2.x, people (well, at least me) is using successfully haystack 2.x in production. What version are you using?n3storm
I'm using haystack 1.x. I ended up re-working my for_sale field as a CharField and now I'm able to filter on it fine. Haystack or Whoosh just doesn't like booleans I guess haha.user2184916

2 Answers

1
votes

I ended up re-working my for_sale field as a CharField and now I'm able to filter on it fine.

Haystack or Whoosh just doesn't like booleans I guess haha.

0
votes

It's probably the same as issue #371 in Haystack:

I noticed that whoosh stores booleans as the Python values True and False, haystack in contrast stored the strings 'true' and 'false', both evaluate as True if queried.

In addition querying my index required to use the strings 't' and 'f' for boolean fields. With this patch it is possible to query with True or False.

Which was apparently fixed in Whoosh, in the 2.4x branch (after 2.41 was released, so not available yet) and 2.5.0 and later.