Django Haystack - Show results without needing a search query?

后端 未结 5 2225
情书的邮戳
情书的邮戳 2021-02-08 10:46

I would like to display all results which match selected facets even though a search query has not been inserted. Similar to how some shop applications work e.g. Amazon

相关标签:
5条回答
  • 2021-02-08 10:54

    If anyone is still looking, there's a simple solution suggested in haystack code:

    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()
    
    0 讨论(0)
  • 2021-02-08 11:02

    Following form display all the result if not query string is present. Now you can add custom filters.

    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
    
    0 讨论(0)
  • 2021-02-08 11:07

    Stumpy Joe Pete's answer is pretty spot on, but as he mentioned, the template if query or page.object_list check is a little hacked. A better way of solving this would be to create your own SearchForm which would still find something if q is empty - will not repost that - AND to customize the SearchView with something like:

    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)
    

    In most cases, you won't even be using the query value, so you could just as well do a quick check if any of the fields is set and return True or something like that.. or of course you can modify the output any way you want (I'm not even 100% sure my solution would work for all field types, but you get the idea).

    0 讨论(0)
  • 2021-02-08 11:10

    Look at SearchQuerySet.

    This should be possible if color and price has been defined in your SearchIndex:

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

    You can limit the query to certain models by adding models(Model) to the SearchQuerySet. So if you want to limit your query to the model Item use:

    sqs = SearchQuerySet().filter(color="blue", price__range=(10,100)).models(Item)
    
    0 讨论(0)
  • 2021-02-08 11:16

    Why No Results?

    I imagine you're using a search template similar to the one in the haystack getting started documentation. This view doesn't display anything if there is no query:

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

    The second problem is that the default search form's search() method doesn't actually search for anything unless there's a query.

    Getting Results

    To get around this, I'm using a custom search form. Here's an abbreviated sample:

    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
    

    Also, don't forget to change the view:

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

    Actually, the view code is a little hackish. It doesn't distinguish query-less searches with no results from search with no parameters.

    Cheers!

    0 讨论(0)
提交回复
热议问题