File: generic_views.py

package info (click to toggle)
django-haystack 3.3.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,504 kB
  • sloc: python: 23,475; xml: 1,708; sh: 74; makefile: 71
file content (140 lines) | stat: -rw-r--r-- 4,017 bytes parent folder | download
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