Django / haystack - 仅基于DateField的year元素进行分面

时间:2015-07-02 03:30:04

标签: python django solr django-haystack datefield

假设我在Django实现中有以下模型:

class Broadcast(models.Model):
    broadcast_date = models.DateField()
    ...

在我的大海捞针/ Solr驱动的搜索结果中,我希望能够仅仅通过播出年份,而不是确切的一天。

我可以为此创建一个新的模型属性,但似乎我应该能够以某种方式在search_indexes模型定义中执行此操作。这是我目前在search_indexes.py中所拥有的内容,仅限于完整日期:

class BroadcastIndex(indexes.SearchIndex, indexes.Indexable):
    text = [...]
    broadcast_date = indexes.DateField(model_attr="broadcast_date", faceted=True)

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

您应该可以使用date_facet()。如果您将gap_by参数设置为year,它将逐年进行。

答案 1 :(得分:1)

只是概述一下我最终做的事情。

首先在我的 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,所以我最终将年份排除在外那个字符串。我使用列表推导来创建一个只包含我想要的数据的新列表,然后将其添加到facets上下文变量中。我使用基于类的视图子类化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 }}&amp;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()

所有这一切都很有效。