【问题标题】:Django / haystack - faceting based only on the year element of a DateFieldDjango / haystack - 仅基于 DateField 的年份元素的分面
【发布时间】:2015-07-02 03:30:03
【问题描述】:

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

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

在我的 haystack/Solr 驱动的搜索结果中,我希望能够仅按播出年份来分面,而不是确切的日期。

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

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

有什么想法吗?

【问题讨论】:

    标签: python django solr django-haystack datefield


    【解决方案1】:

    您应该可以使用date_facet()。如果将其gap_by 参数设置为year,它将按年分面。

    【讨论】:

    • 这似乎是正确的方向,但我不确定如何从模板访问结果数据。我需要使用特定的标签吗?还是我需要在某处的视图代码中解析它,并在渲染器中显式地将其作为新的上下文变量传递?
    • 这有点帮助,谢谢。他们没有提到的是 date_facet() 方法的结果存储在 facets.dates.[name_of_your_date_field] 中。它们也以 yyyy-01-01:00:00:00 格式返回,因此在您只能显示年份之前,您仍然需要进行一些文本处理。也没有任何明显的方法可以通过返回的日期计数数据实际过滤您的搜索——这就是我目前正在努力解决的问题。
    【解决方案2】:

    只是为了概述一下我最终做了什么。

    首先在我的 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 }}&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()
    

    这一切都很好。

    【讨论】:

      猜你喜欢
      • 2011-01-11
      • 2011-03-05
      • 2019-02-09
      • 1970-01-01
      • 2021-12-31
      • 2010-12-03
      • 1970-01-01
      • 1970-01-01
      • 2018-03-26
      相关资源
      最近更新 更多