只是为了概述一下我最终做了什么。
首先在我的 urls.py 文件中,我使用 date_facet() 包含了一个自定义 SearchQuerySet(感谢 Adrian Ghiuta!),我将它传递给我的搜索视图:
...
from haystack.forms import FacetedSearchForm
from haystack.query import SearchQuerySet
sqs = SearchQuerySet().date_facet('broadcast_date', start_date=date(1955, 1, 1), end_date=date(2015, 1, 1), gap_by="year")
urlpatterns = [
...
url(r'^search/', views.SarkSearch(form_class=FacetedSearchForm, searchqueryset=sqs), name='haystack_search'),
]
date_facet() 函数确实提供了一个带有年份计数的分面日期字典,但返回的键的格式为 yyyy-01-01:00:00:00,所以我最终将年份从中分割出来细绳。我使用列表推导来创建一个仅包含我想要的数据的新列表,然后将其添加到构面上下文变量中。我使用的是基于类的视图子类化 FacetedSearchView,所以我需要将所有处理代码放在 extra_context() 函数中:
class FooSearch(FacetedSearchView):
def extra_content(self):
extra = super(FooSearch, self).extra_context()
dates = extra['facets']['dates']['broadcast_date']
dates = sorted([[year[:4], count] for year, count in dates.items() if count > 0])
extra['facets']['dates']['broadcast_date'] = dates
return extra
现在我有了返回的年份方面和计数,我需要想出一种方法来将实际搜索结果缩小到仅给定年份内的那些。在我的搜索模板中,我使用 GET 变量“year_facet”将每个返回的构面日期绑定到构面链接。看起来像这样:
<dl>
{% if facets.dates.broadcast_date %}
<dt>Broadcast dates</dt>
{% for date in facets.dates.broadcast_date %}
<dd><a href="{{ request.get_full_path }}&year_facet={{ date.0 }}">{{ date.0 }}</a> ({{ date.1 }})</dd>
{% endfor %}
{% endif %}
{% if 'year_facet' in request.get_full_path %}
<!-- I want a way to clear the facet if one is present -->
<dd><a href="?q={{ query }}"><em>see all</em></a></dd>
{% endif %}
</dl>
既然已经设置了链接,我需要一种方法来让我的视图在选择基于年份的日期方面时实际缩小结果。为此,在我的搜索视图中,我重写了 get_results() 函数以包含给定年份内所有日期的日期过滤器:
def get_results(self):
if 'year_facet' in self.request.GET:
year = int(self.request.GET['year_facet'])
return self.form.search().filter(broadcast_date__lte=datetime.date(year, 12, 31)).filter(broadcast_date__gte=datetime.date(year, 1, 1))
return self.form.search()
这一切都很好。