Source code for parasolr.django.views
import calendar
import logging
from django.utils.cache import get_conditional_response
from django.views.generic.base import View
from parasolr.django import SolrQuerySet
from parasolr.solr import SolrClientException
from parasolr.utils import solr_timestamp_to_datetime
logger = logging.getLogger(__name__)
[docs]class SolrLastModifiedMixin(View):
"""View mixin to add last modified headers based on Solr.
By default, searches entire solr collection and returns the most
recent last modified value (assumes **last_modified** field).
To filter for items specific to your view, either
set :attr:`solr_lastmodified_filters` or
implement :meth:`get_solr_lastmodified_filters`.
"""
#: solr query filter for getting last modified date
solr_lastmodified_filters = {} # by default, find all
[docs] def get_solr_lastmodified_filters(self):
"""Get filters for last modified Solr query. By default returns
:attr:`solr_lastmodified_filters`."""
return self.solr_lastmodified_filters
[docs] def last_modified(self):
"""Return last modified :class:`datetime.datetime` from the
specified Solr query"""
filter_qs = self.get_solr_lastmodified_filters()
sqs = (
SolrQuerySet()
.filter(**filter_qs)
.order_by("-last_modified")
.only("last_modified")
)
try:
# Solr stores date in isoformat; convert to datetime
return solr_timestamp_to_datetime(sqs[0]["last_modified"])
# skip extra call to Solr to check count and just grab the first
# item if it exists
except (IndexError, KeyError, SolrClientException) as err:
# if a syntax or other solr error happens, no date to return
# report the error, but don't fail since the view may still
# be able to render normally
logger.error("Failed to retrieve last modified: %s" % err)
# TODO: if possible, report view / args / url that triggering
# the error
[docs] def dispatch(self, request, *args, **kwargs):
"""Wrap the dispatch method to add a last modified header if
one is available, then return a conditional response."""
# NOTE: this doesn't actually skip view processing,
# but without it we could return a not modified for a non-200 response
response = super(SolrLastModifiedMixin, self).dispatch(request, *args, **kwargs)
last_modified = self.last_modified()
if last_modified:
# remove microseconds so that comparison will pass,
# since microseconds are not included in the last-modified header
last_modified = last_modified.replace(microsecond=0)
response["Last-Modified"] = last_modified.strftime(
"%a, %d %b %Y %H:%M:%S GMT"
)
# convert the same way django does so that they will
# compare correctly
last_modified = calendar.timegm(last_modified.utctimetuple())
return get_conditional_response(
request, last_modified=last_modified, response=response
)