]> git.0d.be Git - panikweb.git/commitdiff
use haystack to fill a 'related' section down in the page
authorFrédéric Péters <fpeters@0d.be>
Sun, 8 Sep 2013 16:31:27 +0000 (18:31 +0200)
committerFrédéric Péters <fpeters@0d.be>
Sun, 8 Sep 2013 16:31:27 +0000 (18:31 +0200)
panikweb/paniktags/templatetags/paniktags.py
panikweb/search.py
panikweb_templates/templates/emissions/emission_detail.html
panikweb_templates/templates/emissions/episode_detail.html
panikweb_templates/templates/emissions/newsitem_detail.html
panikweb_templates/templates/includes/related.html [new file with mode: 0644]

index 433fb88accb3086dda2dd07ae5f8561375f1b6ff..fecc41a09eca189774b3763618631a24ac53cc66 100644 (file)
@@ -14,6 +14,7 @@ from datetime import datetime, timedelta
 from emissions.utils import period_program
 
 from panikweb import utils
+from panikweb import search
 
 register = template.Library()
 
@@ -217,3 +218,8 @@ def rfc822(datetime):
     if datetime is None:
         return ''
     return email.utils.formatdate(time.mktime(datetime.timetuple()))
+
+@register.inclusion_tag('includes/related.html', takes_context=False)
+def related_objects(object):
+    sqs = search.MoreLikeThisSearchQuerySet()
+    return {'more_like_this': sqs.more_like_this(object)[:12]}
index db84db2f952af673c1340a977a52966f4d282cbd..420f0b554895114b6ce5f3a709d95de1b7af758a 100644 (file)
@@ -1,6 +1,114 @@
+import haystack.backends.solr_backend
+from haystack.query import SearchQuerySet
+from haystack.constants import ID, DJANGO_CT, DJANGO_ID
+from haystack.utils import get_identifier
+
+
+from django.conf import settings
+
+
+class MoreLikeThisSearchQuerySet(SearchQuerySet):
+    def more_like_this(self, model_instance, **kwargs):
+        clone = self._clone()
+        clone.query.more_like_this(model_instance, **kwargs)
+        return clone
+
+
+class CustomSolrSearchQuery(haystack.backends.solr_backend.SolrSearchQuery):
+    def more_like_this(self, model_instance, **kwargs):
+        self._more_like_this = True
+        self._mlt_instance = model_instance
+
+    def run_mlt(self, **kwargs):
+        """Builds and executes the query. Returns a list of search results."""
+        if self._more_like_this is False or self._mlt_instance is None:
+            raise MoreLikeThisError("No instance was provided to determine 'More Like This' results.")
+
+        additional_query_string = self.build_query()
+        search_kwargs = {
+            'start_offset': self.start_offset,
+            'result_class': self.result_class,
+            'models': self.models,
+            'mlt.fl': 'tags',
+        }
+
+        if self.end_offset is not None:
+            search_kwargs['end_offset'] = self.end_offset - self.start_offset
+
+        results = self.backend.more_like_this(self._mlt_instance, additional_query_string, **search_kwargs)
+        self._results = results.get('results', [])
+        self._hit_count = results.get('hits', 0)
+
+
+class CustomSolrSearchBackend(haystack.backends.solr_backend.SolrSearchBackend):
+    def more_like_this(self, model_instance, additional_query_string=None,
+                       start_offset=0, end_offset=None, models=None,
+                       limit_to_registered_models=None, result_class=None, **kwargs):
+        from haystack import connections
+
+        # Deferred models will have a different class ("RealClass_Deferred_fieldname")
+        # which won't be in our registry:
+        model_klass = model_instance._meta.concrete_model
+
+        index = connections[self.connection_alias].get_unified_index().get_index(model_klass)
+        field_name = index.get_content_field()
+        params = {
+            'fl': '*,score',
+            'mlt.fl': 'text,title',
+            'mlt.qf': 'text^0.3 tags^2.0 title^1.0',
+        }
+
+        if start_offset is not None:
+            params['start'] = start_offset
+
+        if end_offset is not None:
+            params['rows'] = end_offset
+
+        narrow_queries = set()
+
+        if limit_to_registered_models is None:
+            limit_to_registered_models = getattr(settings, 'HAYSTACK_LIMIT_TO_REGISTERED_MODELS', True)
+
+        if models and len(models):
+            model_choices = sorted(['%s.%s' % (model._meta.app_label, model._meta.module_name) for model in models])
+        elif limit_to_registered_models:
+            # Using narrow queries, limit the results to only models handled
+            # with the current routers.
+            model_choices = self.build_models_list()
+        else:
+            model_choices = []
+
+        if len(model_choices) > 0:
+            if narrow_queries is None:
+                narrow_queries = set()
+
+            narrow_queries.add('%s:(%s)' % (DJANGO_CT, ' OR '.join(model_choices)))
+
+        if additional_query_string:
+            narrow_queries.add(additional_query_string)
+
+        if narrow_queries:
+            params['fq'] = list(narrow_queries)
+
+        query = "%s:%s" % (ID, get_identifier(model_instance))
+
+        try:
+            raw_results = self.conn.more_like_this(query, field_name, **params)
+        except (IOError, SolrError) as e:
+            if not self.silently_fail:
+                raise
+
+            self.log.error("Failed to fetch More Like This from Solr for document '%s': %s", query, e)
+            raw_results = EmptyResults()
+
+        return self._process_results(raw_results, result_class=result_class)
+
+
+haystack.backends.solr_backend.SolrEngine.query = CustomSolrSearchQuery
+haystack.backends.solr_backend.SolrEngine.backend = CustomSolrSearchBackend
+
 from haystack.views import search_view_factory, FacetedSearchView
 from haystack.forms import FacetedSearchForm
-from haystack.query import SearchQuerySet
 
 
 class SearchView(FacetedSearchView):
index dd08f7e638e5a895088778537abfd5599c87c3ed..945d6c016c646e6df2f72dea47dcc5e082bd426c 100644 (file)
        </div>
 </div>
 {% endblock %}
-{% block related %}
-       {% if related %}
-               <div class="padded">
-                       <div class="wrapper">
-                               <h2>Related</h2>
-                               <ul class="custom columns list">
-                               {% for result in related %}
-                                       <li class="item {% if episode.emission.categories.all.count = 0 %}nocat{% endif %} {% for category in episode.emission.categories.all %} {{ category|slugify }}{% endfor %}">
-                                               {% search_result_template result %}                     
-                                       </li>
-                               {% endfor %}
-                               </ul>
-                       </div>
-               </div>          
-       {% endif %}                     
-{% endblock %}
+
 {% block links %}
 {% endblock %}
+
+{% block related %}
+{% related_objects object=emission %}
+{% endblock %}
index a0ed0a5d870c54ad4b363e19073ccd751f8a070b..32f1f4b7acb58cadbbbfde30a738d569ae0990ab 100644 (file)
@@ -4,3 +4,6 @@
 {% load staticfiles %}
 {% block title %}{{ episode.title }} - {{ episode.emission.title }} {% endblock %}
 
+{% block related %}
+{% related_objects object=episode %}
+{% endblock %}
index 5a0e78527e2692f075d7501bd8ef06cbdc60bc8f..ad00fcdc55408e55055ee738347021018ad256a7 100644 (file)
        </div>
 </div>
 {% endblock %}
+
 {% block related %}
-       {% if related %}
-               <div class="padded">
-                       <div class="wrapper">
-                               <h2>Related</h2>
-                               <ul class="custom columns list">
-                               {% for result in related %}
-                                       <li class="item {% if episode.emission.categories.all.count = 0 %}nocat{% endif %} {% for category in episode.emission.categories.all %} {{ category|slugify }}{% endfor %}">
-                                               {% search_result_template result %}                     
-                                       </li>
-                               {% endfor %}
-                               </ul>
-                       </div>
-               </div>          
-       {% endif %}                     
+{% related_objects object=newsitem %}
 {% endblock %}
diff --git a/panikweb_templates/templates/includes/related.html b/panikweb_templates/templates/includes/related.html
new file mode 100644 (file)
index 0000000..aaba5be
--- /dev/null
@@ -0,0 +1,20 @@
+{% load paniktags %}
+<div class="padded">
+       <div class="wrapper">
+               <h2>Related</h2>
+
+               <ul id="search-results" class="list columns padded cf">
+
+               {% for result in more_like_this %}
+                       {% if result.object.title %}
+                       <li class="ellipsis">
+                               {% search_result_template result %}
+                       </li>
+                       {% endif %}
+               {% endfor %}
+
+
+               </ul>
+
+       </div>
+</div>