django-haystack使用以及多模型搜索 2020年09月13日 未雨晴空 0评论 304阅读 0喜欢 阅读模式 隐藏边栏 显示边栏 # 什么是django-haystack? 官网的介绍如下 Haystack provides modular search for Django,It features a unified, familiar API that allows you to plug in different search backends (such as Solr, Elasticsearch, Whoosh, Xapian, etc.) without having to modify your code. 翻译过来就是 haystack提供了模块化的Django搜索框架,它具有一个统一的,熟悉的API可让您在不同的搜索后端(如Solr,Elasticsearch,Whoosh,Xapian等等)插件,而无需修改代码。 # 安装依赖库以及更换分词器 `pip install whoosh django-haystack jieba` 依次用到的是whoosh搜索引擎,django-haystack搜索框架,jieba分词之所以需要jieba库是因为Whoosh自带的是英文分词,对中文的分词支持不是太好。具体修改方式为拷贝`/haystack/backends/whoosh_backend.py`放到`/blog/blog/`目录下,更改文件名为`whoosh_cn_backend.py`需要修改的部分为 ```python ... from jieba.analyse import ChineseAnalyzer ... else: schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=ChineseAnalyzer(), field_boost=field_class.boost, sortable=True) ``` 在settings中添加Haystack到Django的`INSTALLED_APPS` ```python INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'haystack', 'article', 'video', ] ``` # 文章应用模型搜索 ## 建立模型 ```python from django.db import models class Article(models.Model): title = models.CharField(max_length=200,verbose_name="文章标题") summary=models.CharField(max_length=500,verbose_name="文章摘要") content = models.TextField(verbose_name="文章内容") views = models.IntegerField(verbose_name='浏览数', default=0) def __str__(self): return self.title ``` ## 创建文章内容检索模板 创建之前先看下haystack的源码 ```python def prepare_template(self, obj): """ Flattens an object for indexing. This loads a template (``search/indexes/{app_label}/{model_name}_{field_name}.txt``) and returns the result of rendering that template. ``object`` will be in its context. """ if self.instance_name is None and self.template_name is None: raise SearchFieldError("This field requires either its instance_name variable to be populated or an explicit template_name in order to load the correct template.") if self.template_name is not None: template_names = self.template_name if not isinstance(template_names, (list, tuple)): template_names = [template_names] else: app_label, model_name = get_model_ct_tuple(obj) template_names = ['search/indexes/%s/%s_%s.txt' % (app_label, model_name, self.instance_name)] t = loader.select_template(template_names) return t.render({'object': obj}) ``` 从上述源码可以看出索引模板文件的路径格式是项目的模板目录下`search/indexes/{应用名}/{模型名}_{变量名}.txt`,其中变量名默认就是索引字段也就是text索引字段,故文章的索引内容模板路径即是这样`search/indexes/article/article_text.txt` 同时根据源码也知道如果不按照约定的路径来,那么就必须要在在应用下的 search_indexes.py里面的模型索引例如如ArticleIndex的 ```python text = indexes.CharField(document=True, use_template=True,template_name="search/indexes/article/article_text.txt") ``` 指定索引模板路径,我个人推荐指定template_name,便于后面的多模型搜索。 * 项目根目录下创建`templates/search/indexes/article/article_text.txt` * 文件内容如下: ```python {{ object.title }} {{ object.summary }} {{ object.content }} ``` ## 创建索引 * 新建`apps/article/search_indexes.py`文件 如果想对应用下的模型建立搜索,则需要在该应用下面建立search_indexes .py文件,且文件名不能修改。内容如下: ```python from haystack import indexes from apps.article.models import Article class ArticleIndex(indexes.SearchIndex, indexes.Indexable): text = indexes.CharField(document=True, use_template=True,template_name="search/indexes/article/article_text.txt") views=indexes.IntegerField(model_attr='views') title=indexes.CharField(model_attr='title') def get_model(self): return Article def index_queryset(self, using='article_search'): return self.get_model().objects.all() ``` **每个索引里面必须有且只能有一个字段为document=True,这代表haystack 和搜索引擎将使用此字段的内容作为索引进行检索。其他的字段并不作为检索数据** 但是如果自定义了SearchView,重写了一些逻辑例如过滤,排序时用到了views, 则必须要加上views=indexes.IntegerField(model_attr='views')方便视图调用,不然会报错,如果没用到则可以不用加上。另外在index_queryset函数里的using默认为None,这里指定具体的搜索引擎,也是避免搜索视图里面忘记指定。 ## 自定义文章搜索视图 ```python from haystack.generic_views import SearchView # 自定义文章搜索视图 class ArticleSearchView(SearchView): # 默认搜索表单字段名 # search_field = 'q' # 返回搜索结果集名称 context_object_name = 'articles' # 设置分页 paginate_by = 10 # 搜索结果指定搜索连接同时以浏览量倒序 queryset = SearchQuerySet().using("article_search").order_by('-views') # 视图模板 template_name = 'search/article_search_list.html' ``` 如果不自定搜索表单,在没有覆盖默认的搜索字段名时,前台的搜索字段需要注意字段名默认为q,即如下 ` © 著作权归作者所有,欢迎转载,转载请说明出处:未雨晴空博客,谢谢理解! 喜欢 打赏 分享 上一篇 下一篇 发表评论 取消回复 电子邮件地址不会被公开。 表情 请输入以http或https开头的URL,格式如:https://oneisall.top 提交评论