Views & Forms — Haystack 2.5.0 documentation (2024)

Note

As of version 2.4 the views in haystack.views.SearchView are deprecated infavor of the new generic views in haystack.generic_views.SearchViewwhich use the standard Django class-based views which are available inevery version of Django which is supported by Haystack.

Haystack comes with some default, simple views & forms as well as somedjango-style views to help you get started and to cover the common cases.Included is a way to provide:

  • Basic, query-only search.

  • Search by models.

  • Search with basic highlighted results.

  • Faceted search.

  • Search by models with basic highlighted results.

Most processing is done by the forms provided by Haystack via the searchmethod. As a result, all but the faceted types (see Faceting) use thestandard SearchView.

There is very little coupling between the forms & the views (other than relyingon the existence of a search method on the form), so you may interchangeablyuse forms and/or views anywhere within your own code.

Forms

SearchForm

The most basic of the form types, this form consists of a single field, theq field (for query). Upon searching, the form will take the cleaned contentsof the q field and perform an auto_query on either the customSearchQuerySet you provide or off a default SearchQuerySet.

To customize the SearchQuerySet the form will use, pass it asearchqueryset parameter to the constructor with the SearchQuerySetyou’d like to use. If using this form in conjunction with a SearchView,the form will receive whatever SearchQuerySet you provide to the view withno additional work needed.

The SearchForm also accepts a load_all parameter (True orFalse), which determines how the database is queried when iterating throughthe results. This also is received automatically from the SearchView.

All other forms in Haystack inherit (either directly or indirectly) from thisform.

HighlightedSearchForm

Identical to the SearchForm except that it tags the highlight method onto the end of the SearchQuerySet to enable highlighted results.

ModelSearchForm

This form adds new fields to form. It iterates through all registered models forthe current SearchSite and provides a checkbox for each one. If no modelsare selected, all types will show up in the results.

HighlightedModelSearchForm

Identical to the ModelSearchForm except that it tags the highlightmethod on to the end of the SearchQuerySet to enable highlighted results onthe selected models.

FacetedSearchForm

Identical to the SearchForm except that it adds a hidden selected_facetsfield onto the form, allowing the form to narrow the results based on the facetschosen by the user.

Creating Your Own Form

The simplest way to go about creating your own form is to inherit fromSearchForm (or the desired parent) and extend the search method. Bydoing this, you save yourself most of the work of handling data correctly andstay API compatible with the SearchView.

For example, let’s say you’re providing search with a user-selectable date rangeassociated with it. You might create a form that looked as follows:

from django import formsfrom haystack.forms import SearchFormclass DateRangeSearchForm(SearchForm): start_date = forms.DateField(required=False) end_date = forms.DateField(required=False) def search(self): # First, store the SearchQuerySet received from other processing. sqs = super().search() if not self.is_valid(): return self.no_query_found() # Check to see if a start_date was chosen. if self.cleaned_data['start_date']: sqs = sqs.filter(pub_date__gte=self.cleaned_data['start_date']) # Check to see if an end_date was chosen. if self.cleaned_data['end_date']: sqs = sqs.filter(pub_date__lte=self.cleaned_data['end_date']) return sqs

This form adds two new fields for (optionally) choosing the start and end dates.Within the search method, we grab the results from the parent form’sprocessing. Then, if a user has selected a start and/or end date, we apply thatfiltering. Finally, we simply return the SearchQuerySet.

Views

Note

As of version 2.4 the views in haystack.views.SearchView are deprecated infavor of the new generic views in haystack.generic_views.SearchViewwhich use the standard Django class-based views which are available inevery version of Django which is supported by Haystack.

New Django Class Based Views

Added in version 2.4.0.

The views in haystack.generic_views.SearchView inherit from Django’s standardFormView.The example views can be customized like any other Django class-based view asdemonstrated in this example which filters the search results in get_queryset:

# views.pyfrom datetime import datefrom haystack.generic_views import SearchViewclass MySearchView(SearchView): """My custom search view.""" def get_queryset(self): queryset = super().get_queryset() # further filter queryset based on some set of criteria return queryset.filter(pub_date__gte=date(2015, 1, 1)) def get_context_data(self, *args, **kwargs): context = super().get_context_data(*args, **kwargs) # do something return context# urls.pyurlpatterns = [ path('/search/', MySearchView.as_view(), name='search_view'),]

Upgrading

Upgrading from basic usage of the old-style views to new-style views is usually as simple as:

  1. Create new views under views.py subclassing haystack.generic_views.SearchViewor haystack.generic_views.FacetedSearchView

  2. Move all parameters of your old-style views from your urls.py to attributes onyour new views. This will require renaming searchqueryset to queryset andtemplate to template_name

  3. Review your templates and replace the page variable with page_obj

Here’s an example:

### old-style views...# urls.pysqs = SearchQuerySet().filter(author='john')urlpatterns = [ path('', SearchView( template='my/special/path/john_search.html', searchqueryset=sqs, form_class=SearchForm ), name='haystack_search'),]### new-style views...# views.pyclass JohnSearchView(SearchView): template_name = 'my/special/path/john_search.html' queryset = SearchQuerySet().filter(author='john') form_class = SearchForm# urls.pyfrom myapp.views import JohnSearchViewurlpatterns = [ path('', JohnSearchView.as_view(), name='haystack_search'),]

If your views overrode methods on the old-style SearchView, you will need torefactor those methods to the equivalents on Django’s generic views. For example,if you previously used extra_context() to add additional template variables orpreprocess the values returned by Haystack, that code would move to get_context_data

Old Method

New Method

extra_context()

get_context_data()

create_response()

dispatch() or get() and post()

get_query()

get_queryset()

Old-Style Views

Deprecated since version 2.4.0.

Haystack comes bundled with three views, the class-based views (SearchView &FacetedSearchView) and a traditional functional view (basic_search).

The class-based views provide for easy extension should you need to alter theway a view works. Except in the case of faceting (again, see Faceting),the SearchView works interchangeably with all other forms provided byHaystack.

The functional view provides an example of how Haystack can be used in moretraditional settings or as an example of how to write a more complex customview. It is also thread-safe.

SearchView(template=None, load_all=True, form_class=None, searchqueryset=None, results_per_page=None)

The SearchView is designed to be easy/flexible enough to override commonchanges as well as being internally abstracted so that only altering a specificportion of the code should be easy to do.

Without touching any of the internals of the SearchView, you can modifywhich template is used, which form class should be instantiated to search with,what SearchQuerySet to use in the event you wish to pre-filter the results.what Context-style object to use in the response and the load_allperformance optimization to reduce hits on the database. These options can (andgenerally should) be overridden at the URLconf level. For example, to have acustom search limited to the ‘John’ author, displaying all models to search byand specifying a custom template (my/special/path/john_search.html), yourURLconf should look something like:

from django.urls import pathfrom haystack.forms import ModelSearchFormfrom haystack.query import SearchQuerySetfrom haystack.views import SearchViewsqs = SearchQuerySet().filter(author='john')# Without threading...urlpatterns = [ path('', SearchView( template='my/special/path/john_search.html', searchqueryset=sqs, form_class=SearchForm ), name='haystack_search'),]# With threading...from haystack.views import SearchView, search_view_factoryurlpatterns = [ path('', search_view_factory( view_class=SearchView, template='my/special/path/john_search.html', searchqueryset=sqs, form_class=ModelSearchForm ), name='haystack_search'),]

Warning

The standard SearchView is not thread-safe. Use thesearch_view_factory function, which returns thread-safe instances ofSearchView.

By default, if you don’t specify a form_class, the view will use thehaystack.forms.ModelSearchForm form.

Beyond this customizations, you can create your own SearchView andextend/override the following methods to change the functionality.

__call__(self, request)

Generates the actual response to the search.

Relies on internal, overridable methods to construct the response. You generallyshould avoid altering this method unless you need to change the flow of themethods or to add a new method into the processing.

build_form(self, form_kwargs=None)

Instantiates the form the class should use to process the search query.

Optionally accepts a dictionary of parameters that are passed on to theform’s __init__. You can use this to lightly customize the form.

You should override this if you write a custom form that needs specialparameters for instantiation.

get_query(self)

Returns the query provided by the user.

Returns an empty string if the query is invalid. This pulls the cleaned queryfrom the form, via the q field, for use elsewhere within the SearchView.This is used to populate the query context variable.

get_results(self)

Fetches the results via the form.

Returns an empty list if there’s no query to search with. This method relies onthe form to do the heavy lifting as much as possible.

build_page(self)

Paginates the results appropriately.

In case someone does not want to use Django’s built-in pagination, itshould be a simple matter to override this method to do what they wouldlike.

extra_context(self)

Allows the addition of more context variables as needed. Must return adictionary whose contents will add to or overwrite the other variables in thecontext.

create_response(self)

Generates the actual HttpResponse to send back to the user. It builds the page,creates the context and renders the response for all the aforementionedprocessing.

basic_search(request, template='search/search.html', load_all=True, form_class=ModelSearchForm, searchqueryset=None, extra_context=None, results_per_page=None)

The basic_search tries to provide most of the same functionality as theclass-based views but resembles a more traditional generic view. It’s both aworking view if you prefer not to use the class-based views as well as a goodstarting point for writing highly custom views.

Since it is all one function, the only means of extension are passing inkwargs, similar to the way generic views work.

Creating Your Own View

As with the forms, inheritance is likely your best bet. In this case, theFacetedSearchView is a perfect example of how to extend the existingSearchView. The complete code for the FacetedSearchView looks like:

class FacetedSearchView(SearchView): def extra_context(self): extra = super().extra_context() if self.results == []: extra['facets'] = self.form.search().facet_counts() else: extra['facets'] = self.results.facet_counts() return extra

It updates the name of the class (generally for documentation purposes) andadds the facets from the SearchQuerySet to the context as the facetsvariable. As with the custom form example above, it relies on the parent classto handle most of the processing and extends that only where needed.

Views & Forms — Haystack 2.5.0 documentation (2024)
Top Articles
Latest Posts
Article information

Author: Mrs. Angelic Larkin

Last Updated:

Views: 6119

Rating: 4.7 / 5 (47 voted)

Reviews: 94% of readers found this page helpful

Author information

Name: Mrs. Angelic Larkin

Birthday: 1992-06-28

Address: Apt. 413 8275 Mueller Overpass, South Magnolia, IA 99527-6023

Phone: +6824704719725

Job: District Real-Estate Facilitator

Hobby: Letterboxing, Vacation, Poi, Homebrewing, Mountain biking, Slacklining, Cabaret

Introduction: My name is Mrs. Angelic Larkin, I am a cute, charming, funny, determined, inexpensive, joyous, cheerful person who loves writing and wants to share my knowledge and understanding with you.