【问题标题】:Django Haystack - Show results without needing a search query?Django Haystack - 无需搜索查询即可显示结果?
【发布时间】:2014-06-13 16:04:40
【问题描述】:

即使没有插入搜索查询,我也想显示与所选方面匹配的所有结果。类似于某些商店应用程序的工作方式,例如亚马逊

e.g. Show all products which are "blue" and between $10-$100.

如果没有指定搜索查询,Haystack 不会返回任何值。

有什么办法可以绕过它吗?

谢谢!

【问题讨论】:

  • 不想投票/接受答案?

标签: python django search solr django-haystack


【解决方案1】:

如果有人还在寻找,干草堆代码中建议了一个简单的解决方案:

https://github.com/toastdriven/django-haystack/blob/master/haystack/forms.py#L34

class SearchForm(forms.Form):
    def no_query_found(self):
    """
    Determines the behavior when no query was found.

    By default, no results are returned (``EmptySearchQuerySet``).

    Should you want to show all results, override this method in your
    own ``SearchForm`` subclass and do ``return self.searchqueryset.all()``.
    """
    return EmptySearchQuerySet()

【讨论】:

    【解决方案2】:

    为什么没有结果?

    我想您正在使用类似于大海捞针getting started documentation 的搜索模板。如果没有查询,此视图不会显示任何内容:

    {% if query %}
        {# Display the results #}
    {% else %}
        {# Show some example queries to run, maybe query syntax, something else? #}
    {% endif %}
    

    第二个问题是默认搜索表单的search() 方法实际上不会搜索任何内容,除非有查询。

    获得结果

    为了解决这个问题,我使用了自定义搜索表单。这是一个简短的示例:

    class CustomSearchForm(SearchForm):
        ...
        def search(self):
            # First, store the SearchQuerySet received from other processing.
            sqs = super(CustomSearchForm, self).search()
    
            if not self.is_valid():
              return sqs
    
            filts = []
    
            # Check to see if a start_date was chosen.
            if self.cleaned_data['start_date']:
                filts.append(SQ(created_date__gte=self.cleaned_data['start_date']))
    
            # Check to see if an end_date was chosen.
            if self.cleaned_data['end_date']:
                filts.append(SQ(created_date__lte=self.cleaned_data['end_date']))
    
            # Etc., for any other things you add
    
            # If we started without a query, we'd have no search
            # results (which is fine, normally). However, if we
            # had no query but we DID have other parameters, then
            # we'd like to filter starting from everything rather
            # than nothing (i.e., q='' and tags='bear' should 
            # return everything with a tag 'bear'.)
            if len(filts) > 0 and not self.cleaned_data['q']:
                sqs = SearchQuerySet().order_by('-created_date')
    
            # Apply the filters
            for filt in filts:
                sqs = sqs.filter(filt)
    
            return sqs
    

    另外,别忘了改变视图:

    {% if query or page.object_list %}
        {# Display the results #}
    {% else %}
        {# Show some example queries to run, maybe query syntax, something else? #}
    {% endif %}
    

    实际上,视图代码有点骇人听闻。它不区分没有结果的无查询搜索和没有参数的搜索。

    干杯!

    【讨论】:

      【解决方案3】:

      SearchQuerySet

      如果您的 SearchIndex 中定义了颜色和价格,这应该是可能的:

      sqs = SearchQuerySet().filter(color="blue", price__range=(10,100))
      

      您可以通过将models(Model) 添加到 SearchQuerySet 来将查询限制为特定模型。因此,如果您想将查询限制为模型 Item 使用:

      sqs = SearchQuerySet().filter(color="blue", price__range=(10,100)).models(Item)
      

      【讨论】:

      • 这让我意识到我的问题出在哪里。谢谢!
      【解决方案4】:

      如果不存在查询字符串,则以下表单显示所有结果。现在您可以添加自定义过滤器了。

      from your_app.forms import NonEmptySearchForm
      url(r'^your_url$', 
      SearchView(template='search.html',searchqueryset=sqs,form_class=NonEmptySearchForm), name='haystack_search'),
      

      forms.py

      #Overridding because the default sqs is always none if no query string is present
      class NonEmptySearchForm(SearchForm):
          def search(self):
              if not self.is_valid():
                  return self.no_query_found()
              sqs = self.searchqueryset.auto_query(self.cleaned_data['q'])
              if self.load_all:
                  sqs = sqs.load_all()
              return sqs
      

      【讨论】:

        【解决方案5】:

        Stumpy Joe Pete 的回答非常准确,但正如他所提到的,模板 if query or page.object_list 检查有点被黑了。解决此问题的更好方法是创建自己的 SearchForm,如果 q 为空,它仍然会找到一些东西 - 不会重新发布 - 并使用以下内容自定义 SearchView

        class MySearchView(SearchView):
            def get_query(self):
                query = []
        
                if self.form.is_valid():
                    for field in self.form:
                        if field.name in self.form.cleaned_data and self.form.cleaned_data[field.name]:
                            query.append(field.name+'='+str(self.form.cleaned_data[field.name]))
        
                return ' AND '.join(query)
        

        在大多数情况下,您甚至不会使用 query 值,因此您也可以快速检查是否设置了任何字段并返回 True 或类似的东西.. 或当然,您可以以任何您想要的方式修改输出(我什至不能 100% 确定我的解决方案是否适用于所有字段类型,但您明白了)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-11-26
          • 2017-08-15
          • 1970-01-01
          • 1970-01-01
          • 2018-07-26
          相关资源
          最近更新 更多