diff --git a/blog/search_indexes.py b/blog/search_indexes.py
index ba966b4..dd50e25 100644
--- a/blog/search_indexes.py
+++ b/blog/search_indexes.py
@@ -9,8 +9,9 @@
class PostIndex(indexes.SearchIndex, indexes.Indexable):
+ # 文章内容
text = indexes.CharField(document=True, use_template=True)
- # 对title字段进行索引
+ # 对标题字段进行索引
title = indexes.CharField(model_attr='title')
def get_model(self):
diff --git a/blog/templates/blog/post_search_list.html b/blog/templates/blog/post_search_list.html
index 30292ee..9668d52 100644
--- a/blog/templates/blog/post_search_list.html
+++ b/blog/templates/blog/post_search_list.html
@@ -1,15 +1,12 @@
{% extends 'mysite/base.html' %}
{% load blog_tags %}
-{% load pagination_tags %}
{% block content %}
{% if list_header %}
{{ list_header }}
{% endif %}
- {% autopaginate posts 10 %}
{% for post in posts %}
{% endfor %}
- {% paginate %}
{% endblock %}
diff --git a/blog/urls.py b/blog/urls.py
index 587a56c..237465c 100644
--- a/blog/urls.py
+++ b/blog/urls.py
@@ -4,7 +4,7 @@
urlpatterns = [
url(r'^$', post_list, name='home'),
- # url(r'^posts/search/$', full_search, name='full_search'),
+ url(r'^posts/search/$', full_search, name='full_search'),
url(r'^posts/tag/(?P\w+)$', post_list_by_tag, name='list_by_tag'),
url(r'^posts/category/(?P\w+)$', post_list_by_category, name='list_by_cg'),
url(r'^posts/archive/(?P[0-9]{4})/(?P[0-9]{1,2})$', post_list_by_ym, name='list_by_ym'),
diff --git a/blog/views.py b/blog/views.py
index 927bd08..f98f320 100644
--- a/blog/views.py
+++ b/blog/views.py
@@ -14,17 +14,17 @@
import json
-# from haystack.forms import SearchForm
+from haystack.forms import SearchForm
# import qiniu
-# def full_search(request):
-# """全局搜索"""
-# keywords = request.GET['q']
-# sform = SearchForm(request.GET)
-# posts = sform.search()
-# return render(request, 'blog/post_search_list.html',
-# {'posts': posts, 'list_header': '关键字 \'{}\' 搜索结果'.format(keywords)})
+def full_search(request):
+ """全局搜索"""
+ keywords = request.GET['q']
+ sform = SearchForm(request.GET)
+ posts = sform.search()
+ return render(request, 'blog/post_search_list.html',
+ {'posts': posts, 'list_header': '关键字 \'{}\' 搜索结果'.format(keywords)})
def get_client_ip(request):
diff --git a/blog/whoosh_cn_backend.py b/blog/whoosh_cn_backend.py
index 5e27b39..e1ac005 100644
--- a/blog/whoosh_cn_backend.py
+++ b/blog/whoosh_cn_backend.py
@@ -1,24 +1,27 @@
-from __future__ import unicode_literals
+# encoding: utf-8
+
+from __future__ import absolute_import, division, print_function, unicode_literals
+
import os
import re
import shutil
import threading
import warnings
-from jieba.analyse import ChineseAnalyzer
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
-from django.db.models.loading import get_model
from django.utils import six
from django.utils.datetime_safe import datetime
-from haystack.backends import BaseEngine, BaseSearchBackend, BaseSearchQuery, log_query, EmptyResults
-from haystack.constants import ID, DJANGO_CT, DJANGO_ID
-from haystack.exceptions import MissingDependency, SearchBackendError
-from haystack.inputs import PythonData, Clean, Exact, Raw
+
+from haystack.backends import BaseEngine, BaseSearchBackend, BaseSearchQuery, EmptyResults, log_query
+from haystack.constants import DJANGO_CT, DJANGO_ID, ID
+from haystack.exceptions import MissingDependency, SearchBackendError, SkipDocument
+from haystack.inputs import Clean, Exact, PythonData, Raw
from haystack.models import SearchResult
-from haystack.utils import get_identifier
from haystack.utils import log as logging
-from haystack.utils import get_model_ct
+from haystack.utils import get_identifier, get_model_ct
+from haystack.utils.app_loading import haystack_get_model
+from jieba.analyse import ChineseAnalyzer
try:
import json
@@ -38,20 +41,21 @@
except ImportError:
raise MissingDependency("The 'whoosh' backend requires the installation of 'Whoosh'. Please refer to the documentation.")
+# Handle minimum requirement.
+if not hasattr(whoosh, '__version__') or whoosh.__version__ < (2, 5, 0):
+ raise MissingDependency("The 'whoosh' backend requires version 2.5.0 or greater.")
+
# Bubble up the correct error.
from whoosh import index
from whoosh.analysis import StemmingAnalyzer
from whoosh.fields import ID as WHOOSH_ID
-from whoosh.fields import Schema, IDLIST, TEXT, KEYWORD, NUMERIC, BOOLEAN, DATETIME, NGRAM, NGRAMWORDS
+from whoosh.fields import BOOLEAN, DATETIME, IDLIST, KEYWORD, NGRAM, NGRAMWORDS, NUMERIC, Schema, TEXT
from whoosh.filedb.filestore import FileStorage, RamStorage
+from whoosh.highlight import highlight as whoosh_highlight
+from whoosh.highlight import ContextFragmenter, HtmlFormatter
from whoosh.qparser import QueryParser
from whoosh.searching import ResultsPage
from whoosh.writing import AsyncWriter
-from whoosh.highlight import HtmlFormatter, highlight as whoosh_highlight, ContextFragmenter
-
-# Handle minimum requirement.
-if not hasattr(whoosh, '__version__') or whoosh.__version__ < (2, 5, 0):
- raise MissingDependency("The 'whoosh' backend requires version 2.5.0 or greater.")
DATETIME_REGEX = re.compile('^(?P\d{4})-(?P\d{2})-(?P\d{2})T(?P\d{2}):(?P\d{2}):(?P\d{2})(\.\d{3,6}Z?)?$')
@@ -189,32 +193,32 @@ def update(self, index, iterable, commit=True):
writer = AsyncWriter(self.index)
for obj in iterable:
- doc = index.full_prepare(obj)
-
- # Really make sure it's unicode, because Whoosh won't have it any
- # other way.
- for key in doc:
- doc[key] = self._from_python(doc[key])
-
- # Document boosts aren't supported in Whoosh 2.5.0+.
- if 'boost' in doc:
- del doc['boost']
-
try:
- writer.update_document(**doc)
- except Exception as e:
- if not self.silently_fail:
- raise
-
- # We'll log the object identifier but won't include the actual object
- # to avoid the possibility of that generating encoding errors while
- # processing the log message:
- self.log.error(u"%s while preparing object for update" % e.__class__.__name__, exc_info=True, extra={
- "data": {
- "index": index,
- "object": get_identifier(obj)
- }
- })
+ doc = index.full_prepare(obj)
+ except SkipDocument:
+ self.log.debug(u"Indexing for object `%s` skipped", obj)
+ else:
+ # Really make sure it's unicode, because Whoosh won't have it any
+ # other way.
+ for key in doc:
+ doc[key] = self._from_python(doc[key])
+
+ # Document boosts aren't supported in Whoosh 2.5.0+.
+ if 'boost' in doc:
+ del doc['boost']
+
+ try:
+ writer.update_document(**doc)
+ except Exception as e:
+ if not self.silently_fail:
+ raise
+
+ # We'll log the object identifier but won't include the actual object
+ # to avoid the possibility of that generating encoding errors while
+ # processing the log message:
+ self.log.error(u"%s while preparing object for update" % e.__class__.__name__,
+ exc_info=True, extra={"data": {"index": index,
+ "object": get_identifier(obj)}})
if len(iterable) > 0:
# For now, commit no matter what, as we run into locking issues otherwise.
@@ -233,16 +237,19 @@ def remove(self, obj_or_string, commit=True):
if not self.silently_fail:
raise
- self.log.error("Failed to remove document '%s' from Whoosh: %s", whoosh_id, e)
+ self.log.error("Failed to remove document '%s' from Whoosh: %s", whoosh_id, e, exc_info=True)
- def clear(self, models=[], commit=True):
+ def clear(self, models=None, commit=True):
if not self.setup_complete:
self.setup()
self.index = self.index.refresh()
+ if models is not None:
+ assert isinstance(models, (list, tuple))
+
try:
- if not models:
+ if models is None:
self.delete_index()
else:
models_to_delete = []
@@ -255,7 +262,11 @@ def clear(self, models=[], commit=True):
if not self.silently_fail:
raise
- self.log.error("Failed to clear documents from Whoosh: %s", e)
+ if models is not None:
+ self.log.error("Failed to clear Whoosh index of models '%s': %s", ','.join(models_to_delete),
+ e, exc_info=True)
+ else:
+ self.log.error("Failed to clear Whoosh index: %s", e, exc_info=True)
def delete_index(self):
# Per the Whoosh mailing list, if wiping out everything from the index,
@@ -603,7 +614,7 @@ def _process_results(self, raw_page, highlight=False, query_string='', spelling_
score = raw_page.score(doc_offset) or 0
app_label, model_name = raw_result[DJANGO_CT].split('.')
additional_fields = {}
- model = get_model(app_label, model_name)
+ model = haystack_get_model(app_label, model_name)
if model and model in indexed_models:
for key, value in raw_result.items():
diff --git a/mysite/settings.py b/mysite/settings.py
index f0f7276..59a47cb 100644
--- a/mysite/settings.py
+++ b/mysite/settings.py
@@ -40,7 +40,7 @@
'django.contrib.staticfiles',
'django.contrib.admin',
# 'xadmin',
- # 'haystack',
+ 'haystack',
'crispy_forms',
'reversion',
'blog',
@@ -148,13 +148,13 @@
# SESSION_CACHE_ALIAS = 'default'
# full text search
-# HAYSTACK_CONNECTIONS = {
-# 'default': {
-# 'ENGINE': 'blog.whoosh_cn_backend.WhooshEngine',
-# 'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
-# },
-# }
-# HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
+HAYSTACK_CONNECTIONS = {
+ 'default': {
+ 'ENGINE': 'blog.whoosh_cn_backend.WhooshEngine',
+ 'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
+ },
+}
+HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
diff --git a/mysite/templates/mysite/base.html b/mysite/templates/mysite/base.html
index 37b9a43..62db57f 100644
--- a/mysite/templates/mysite/base.html
+++ b/mysite/templates/mysite/base.html
@@ -54,7 +54,7 @@