最近一直在看django by example, 但由于这个教程是很久之前的了,而且搜索功能也是用solr去做的,然后去网上找代码也基本上没有,想了想,算了,干脆自己写了,应该也不难,但没想到搞了这么久,不过最终还是写出来了。。。
首先这个haystack只支持1.x和2.x版本的els, 所以不要装错了,我装了2.x的els, 当然els安装之前肯定要装java的,首先settings.py设置如下:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'haystack',
'blog',
'taggit',
'django.contrib.sites',
'django.contrib.sitemaps',
]
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.elasticsearch2_backend.Elasticsearch2SearchEngine',
'URL': 'http://127.0.0.1:9200/',
'INDEX_NAME': 'blog_search',
},
}
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'由于我是想搜索博客的内容,models.py中的Post数据库字段如下:
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250,
unique_for_date='publish')
author = models.ForeignKey(User, related_name='blog_posts', on_delete=models.CASCADE)
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10,
choices=STATUS_CHOICES,
default='draft')
objects = models.Manager()
published_objects = PublishedManager()
tags = TaggableManager()
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post_detail', args=[self.publish.year,
self.publish.strftime('%m'),
self.publish.strftime('%d'),
self.slug])然后forms.py我继承了haystack.forms的SearchForm
class BlogSearchForm(SearchForm):
def no_query_found(self):
return self.searchqueryset.all()接下来是search_indexes.py, 这个是必须要写的
from haystack import indexes
from .models import Post
class PostIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
title = indexes.CharField(model_attr='title')
slug = indexes.CharField(model_attr='slug')
body = indexes.CharField(model_attr='body')
def get_model(self):
return Post这里的text字段基本上规范都是这样,然后有use_template=True, 这样就允许用数据模板去建立搜索引擎去索引文件。
然后要去建立模板文件,路径为templates/search/indexes/blog/post_text.txt,这样搜索引擎才知道根据什么字段去建立索引,
{{object.title}}
{{object.slug}}
{{object.body}}然后可以敲命令来建立索引了,python manage.py rebuild_index, 成功以后开始写views.py
def post_search(request):
form = BlogSearchForm()
cd = None
results = None
total_results = None
if 'q' in request.GET:
form = BlogSearchForm(request.GET)
if form.is_valid():
cd = form.cleaned_data
results = SearchQuerySet().models(Post).filter(content=cd['q']).load_all()
total_results = results.count()
return render(request, 'search/search.html', {'form': form,
'cd': cd,
'results': results,
'total_results': total_results})这里有一些调试小技巧:有时当你并知道搜索出来的东西有什么属性的时候,可以用print(dir())的方法去调试,不然在框架里实际上很难去调整。
我一开始views.py的代码实际上是这样写的:
def post_search(request):
form = BlogSearchForm(request.GET) # 一定要将form传到html中,否则并不会将表单显示出来
blogs = form.search()
print(dir(blogs[0]))
return render(request, 'search/search.html', {'blogs': blogs, 'form': form})然后els的普通查询是q=query这种形式的,与原教程solr的query有点区别。
最后把views.py里面变量传到html就可以啦,所以search.html是这样的:
{% extends "blog/base.html" %}
{% block title %}Search{% endblock %}
{% block content %}
{% if "q" in request.GET %}
<h1>Posts containing "{{ cd.q }}"</h1>
<h3>Found {{ total_results }} result{{ total_results|pluralize }}</h3>
{% for result in results %}
{% with post=result.object %}
<h4><a href="{{ post.get_absolute_url }}">{{ post.title }}</a></h4>
{{ post.body|truncatewords:5 }}
{% endwith %}
{% empty %}
<p>There are no results for your query.</p>
{% endfor %}
<p><a href="{% url "blog:post_search" %}">Search again</a></p>
{% else %}
<h1>Search for posts</h1>
<form action="" method="get">
{{ form.as_p }}
<input type="submit" value="Search">
</form>
{% endif %}
{% endblock %}最后代码已经放到我的github上面了
willwinworld/web-related
至此,django by example的前3章就完美搞定了,其实还是要弄清楚数据是怎么流动的,api摸摸肯定会越来越熟练。还要补充一点的是,每次新建索引的时候,可能需要重复的删除els里面的内容,所以在git客户端里可以一次性将所有的doc删除完,命令是curl -X DELETE 'http://localhost:9200/_all'
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31509949/viewspace-3146252/ ,如需转载,请注明出处,否则将追究法律责任。