Джанго-стог сена с свистом - не может фильтровать по логическому полю
Что ж, я много часов тянул свои волосы над этим и решил, что пришло время обратиться за помощью, так как я не могу выяснить, почему это происходит с помощью поиска в Google...
По сути, я делаю приложение типа объявления, и мне нужна форма поиска для поиска в базе данных и фильтрации по различным критериям. Я использую django, haystack и whoosh, и у меня это работает почти идеально, но я не могу заставить его фильтровать логические переменные. Я успешно настроил фильтрацию на категорию Charfield, и она работает отлично, но когда я пытаюсь добавить фильтр на основе логического значения for_sale (или любого логического значения в этом отношении), он ничего не фильтрует и возвращает те же результаты, как если бы это никогда не называлось (я проверил, и это фактически вызывается).
У кого-нибудь есть идеи?
Соответствующая часть моей модели:
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)
Это мой класс индекса листинга:
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)
Мой расширенный SearchForm и 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
И, наконец, мой текстовый файл индекса листинга:
{{ object.title }}
{{ object.text_content }}
{{ object.created }}
{{ object.url }}
{{ object.category }}
{{ object.price }}
{{ object.city }}
{{ object.for_sale }}
2 ответа
Я закончил работу над своим полем for_sale как CharField, и теперь я могу фильтровать его нормально.
Haystack или Whoosh просто не любит логические значения, я думаю, ха-ха.
Вероятно, это то же самое, что и проблема № 371 в стоге сена:
Я заметил, что whoosh хранит логические значения как значения Python True и False, а в стоге сена, напротив, хранятся строки 'true' и 'false', которые при запросе оцениваются как True.
Кроме того, для запроса моего индекса необходимо использовать строки 't' и 'f' для логических полей. С помощью этого патча можно выполнять запросы с True или False.
Который, по-видимому, был исправлен в Whoosh, в ветке 2.4x (после выпуска 2.41, пока недоступной) и 2.5.0 и позже.