1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
from django.conf import settings
from django.core.paginator import Paginator
from django.views.generic import FormView
from django.views.generic.edit import FormMixin
from django.views.generic.list import MultipleObjectMixin
from .forms import FacetedSearchForm, ModelSearchForm
from .query import SearchQuerySet
RESULTS_PER_PAGE = getattr(settings, "HAYSTACK_SEARCH_RESULTS_PER_PAGE", 20)
class SearchMixin(MultipleObjectMixin, FormMixin):
"""
A mixin that allows adding in Haystacks search functionality into
another view class.
This mixin exhibits similar end functionality as the base Haystack search
view, but with some important distinctions oriented around greater
compatibility with Django's built-in class based views and mixins.
Normal flow:
self.request = request
self.form = self.build_form()
self.query = self.get_query()
self.results = self.get_results()
return self.create_response()
This mixin should:
1. Make the form
2. Get the queryset
3. Return the paginated queryset
"""
template_name = "search/search.html"
load_all = True
form_class = ModelSearchForm
context_object_name = None
paginate_by = RESULTS_PER_PAGE
paginate_orphans = 0
paginator_class = Paginator
page_kwarg = "page"
form_name = "form"
search_field = "q"
object_list = None
def get_queryset(self):
if self.queryset is None:
self.queryset = SearchQuerySet()
return self.queryset
def get_form_kwargs(self):
"""
Returns the keyword arguments for instantiating the form.
"""
kwargs = {"initial": self.get_initial()}
if self.request.method == "GET":
kwargs.update({"data": self.request.GET})
kwargs.update(
{"searchqueryset": self.get_queryset(), "load_all": self.load_all}
)
return kwargs
def form_invalid(self, form):
context = self.get_context_data(
**{self.form_name: form, "object_list": self.get_queryset()}
)
return self.render_to_response(context)
def form_valid(self, form):
self.queryset = form.search()
context = self.get_context_data(
**{
self.form_name: form,
"query": form.cleaned_data.get(self.search_field),
"object_list": self.queryset,
}
)
return self.render_to_response(context)
class FacetedSearchMixin(SearchMixin):
"""
A mixin that allows adding in a Haystack search functionality with search
faceting.
"""
form_class = FacetedSearchForm
facet_fields = None
date_facet_fields = None
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs.update({"selected_facets": self.request.GET.getlist("selected_facets")})
return kwargs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({"facets": self.queryset.facet_counts()})
return context
def get_queryset(self):
qs = super().get_queryset()
for field in self.facet_fields:
qs = qs.facet(field)
if self.date_facet_fields:
for field in self.date_facet_fields:
qs = qs.date_facet(**field)
return qs
class SearchView(SearchMixin, FormView):
"""A view class for searching a Haystack managed search index"""
def get(self, request, *args, **kwargs):
"""
Handles GET requests and instantiates a blank version of the form.
"""
form_class = self.get_form_class()
form = self.get_form(form_class)
if form.is_valid():
return self.form_valid(form)
return self.form_invalid(form)
class FacetedSearchView(FacetedSearchMixin, SearchView):
"""
A view class for searching a Haystack managed search index with
facets
"""
pass
|