Source code for cdhweb.pages.views
import operator
from django.utils.cache import get_conditional_response
from django.views.generic import ListView, TemplateView
from django.views.generic.base import View
from django.views.generic.edit import FormMixin
from wagtail.core.models import Page
from wagtail.search.utils import parse_query_string
from cdhweb.pages.forms import SiteSearchForm
[docs]class LastModifiedMixin(View):
"""Mixin that adds last-modified timestamps to response for detail views.
Uses Django's get_conditional_response to return a 304 if object has not
been modified since time specified in the HTTP if-modified-since header.
"""
# override to customize which attribute to use as modification date
lastmodified_attr = "updated"
[docs] def last_modified(self):
"""Get the last modified date of the view object."""
return getattr(self.get_object(), self.lastmodified_attr)
def dispatch(self, request, *args, **kwargs):
response = super(LastModifiedMixin, self).dispatch(request, *args, **kwargs)
# NOTE: remove microseconds so that comparison will pass,
# since microseconds are not included in the last-modified header
last_modified = self.last_modified()
if last_modified:
last_modified = self.last_modified().replace(microsecond=0)
response["Last-Modified"] = last_modified.strftime(
"%a, %d %b %Y %H:%M:%S GMT"
)
last_modified = last_modified.timestamp()
return get_conditional_response(
request, last_modified=last_modified, response=response
)
[docs]class LastModifiedListMixin(LastModifiedMixin):
"""Mixin that adds last-modified timestamps to response for list views.
Uses Django's get_conditional_response to return a 304 if none of the
objects in the list have been modified since time specified in the HTTP
if-modified-since header.
"""
[docs] def last_modified(self):
"""Get the most recent modification date among all view objects."""
queryset = self.get_queryset()
if queryset.exists():
return getattr(
queryset.order_by(self.lastmodified_attr).reverse().first(),
self.lastmodified_attr,
)
[docs]class SiteSearchView(ListView, FormMixin):
"""Search across all pages on the site."""
model = Page
form_class = SiteSearchForm
paginate_by = 10
page_title = "Search"
template_name = "cdhpages/search.html"
[docs] def get_queryset(self):
# get keyword query; support filters & phrase matching with double quotes
# see https://docs.wagtail.io/en/stable/topics/search/searching.html#query-string-parsing
q = self.request.GET.get("q", "")
_filters, query = parse_query_string(q) # not using these filters yet
query.operator = "or" # set query operator to OR (default is AND)
# execute search; exclude unpublished pages.
# NOTE results sorted by relevance by default; to override sort the QS
# first and then pass order_by_relevance=false to .search()
return self.model.objects.live().search(query)
[docs] def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({"page_title": self.page_title})
return context
[docs]class OpenSearchDescriptionView(TemplateView):
"""Basic open search description for searching the site via browser or
other tools."""
# adapted from ppa-django:
# https://github.com/Princeton-CDH/ppa-django/blob/main/ppa/archive/views.py#L629-L634
template_name = "cdhpages/opensearch_description.xml"
content_type = "application/opensearchdescription+xml"