注意:系統環境為Ubuntu18
一、docker安裝
0:如果之前有安裝過docker使用以下命令卸載:
sudo apt-get remove docker docker-engine docker.io containerd runc
docker安裝官網參考:
https://docs.docker.com/install/linux/docker-ce/ubuntu/
1:首先更新apt
sudo apt-get update
2:添加證書安裝包以允許apt通過HTTPS:
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
3:添加docker官方密鑰
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
4:添加倉庫
sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable"
5:安裝docker ce
sudo apt-get install docker-ce docker-ce-cli containerd.io
6:測試
sudo docker run hello-world
7:添加當前系統用戶到docker用戶組
sudo usermod -aG docker 用戶名
docker 拓展命令:
docker images :查看所有啟動成功的鏡像
docker ps -a :查看所有
docker logs 容器id :查看容器日志
docker 如果啟動容器失敗,就先刪除容器,刪除目錄,再次執行安裝。
二、使用docker安裝Elasticsearch
1:獲取鏡像
docker image pull delron/elasticsearch-ik:2.4.6-1.0
如果pull拉取很慢可以從我的百度雲中下載,然后傳到Linux系統中然后使用docker命令導入
鏈接:https://pan.baidu.com/s/1zXBR_uHSFxK5xNxklGV1pQ
提取碼:96iw
docker load -i elasticsearch-ik-2.4.6_docker.tar
查看本地倉庫是否有這個鏡像
docker images 或 docker image ls
將下載的elasticsearch.zip上傳到Linux系統中的家目錄,然后解壓。在目錄中的elasticsearch/config/elasticsearch.yml第54行更改IP地址為0.0.0.0,端口改為8002,默認為9002
解壓命令:
unzip elasticsearch.zip
2:創建docker容器並運行
根據拉取到本地的鏡像創建容器,需要將elasticsearch/config配置文件所在目錄修改為你自己的路徑
docker run -dti --network=host --name=elasticsearch -v /home/上面上傳后解壓出來的文件路徑地址/elasticsearch/config:/usr/share/eleaticsearh/config delron/elasticsearch-ik:2.4.6-1.0
查看是否創建成功,如果STATUS為Up則創建成功
docker container ls -a 或 docker ps -a

測試 curl 127.0.0.1:8002

3:進入項目的虛擬環境中,安裝以下包
pip install django-haystack pip install elasticsearch==2.4.1
4:在django項目配置,在settings.py文件中加入下面配置。
4-1:在INSTALLED_APPS節點中注冊haystack
INSTALLED_APPS = [
...
'haystack',
...
]
4-2:加入配置
# 建立連接
ELASTICSEARCH_DSL = {
'default':{
'host':'127.0.0.1:8002'
},
}
# 配置Haystack HAYSTACK_CONNECTIONS = { 'default': { 'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine', 'URL': 'http://127.0.0.1:8002/', # 此處為elasticsearch運行的服務器ip地址,端口號固定為9200 'INDEX_NAME': 'mysite', # 指定elasticsearch建立的索引庫的名稱 }, } # 當添加、修改、刪除數據時,自動生成索引,當數據庫改變時候,會自動更新索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
# 每頁顯示多少條數據
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 20
5:建立索引
在需要創建索引的實體中創建search_indexes.py(文件名固定寫法)

5-1:search_indexes.py文件內容如下:
from haystack import indexes
from .models import News # 導入模型類
# 建索引類
# 模型名稱+Index(固定的)
class NewsIndex(indexes.SearchIndex, indexes.Indexable):
'''
News索引數據庫模型
'''
# 這個主要是使用5-2來建立索引
text = indexes.CharField(document=True, use_template=True)
# 以下是為了在使用時 news.id 如果沒有寫就需要news.object.id
id = indexes.IntegerField(model_attr='id')
title = indexes.CharField(model_attr='title')
digest = indexes.CharField(model_attr='digest')
content = indexes.CharField(model_attr='content')
image_url = indexes.CharField(model_attr='image_url')
def get_model(self):
'''
返回建立索引模型
'''
return News
def index_queryset(self, using=None):
'''
返回要建立索引的數據查詢集
:param using:
:return:
'''
return set.get_model().objects.filter(is_delete=False, tag_id=1)
# return set.get_model().objects.filter(is_delete=False,tag_id=[1,2,3,4,5])
5-2:創建模板
# 需要在templates文件夾中創建一個search/indexes/app名稱/模型名稱小寫_text.txt文件(固定結構)

news_text.txt內容為:需要建立的索引

6:生成索引
通過xshell進入項目進入虛擬環境執行
python manage.py rebuild_index

7: 分頁搜索接口/方法
7-1
from haystack.views import SearchView as _SearchView
from .models import News # 導入模型類
from .models import HotNews
from mysite import setttings
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render
from django.views import View
class SearchView(_SearchView):
# 模板文件
template = 'news/search.html'
# 重寫響應方式,如果請求參數為空,返回模型News的熱門新聞數據,否則根據參數q搜索相關數據
def create_response(self):
kw = self.request.GET.get('q', '')
if not kw:
show_all = True
hot_news = HotNews.objects.select_related(
'News'
).only(
'news__title',
'news__image_url',
'news__id'
).filter(
is_delete=False
).order_by(
'priority',
'-news__clicks'
)
paginator = Paginator(hot_news, setttings.HAYSTACK_SEARCH_RESULTS_PER_PAGE)
try:
page = paginator.page(int(self.request.GET.get('page', 1)))
except PageNotAnInteger:
# 如果參數page的數據類型不是整數,則返回第一頁數據
page = paginator.page(1)
except EmptyPage:
# 用戶訪問的頁數大於實際的頁數,則返回最后一頁的數據
page = paginator.page(paginator.num_pages)
return render(self.request, self.template, locals())
else:
show_all = False
qs = super(SearchView, self).create_response()
return qs
7-2:在app中的urls中設置url
path('search/',view.SearchView(),name='search')
7-3:前端部分代碼
<div class="content">
<!-- search-list start -->
{% if not show_all %}
<div class="search-result-list">
<h2 class="search-result-title">
搜索結果 <span style="font-weight: 700;color: #ff6620;">{{ paginator.num_pages }}</span>頁
</h2>
<ul class="news-list">
{% for one_news in page.object_list %}
<li class="news-item clearfix">
<a href="{% url 'news:detail' one_news.id %}" class="news-thumbnail"
target="_blank">
<img src="{{ one_news.object.image_url }}">
</a>
<div class="news-content">
<h4 class="news-title">
<a href="{% url 'news:detail' one_news.id %}">
{% highlight one_news.title with query %}
</a>
</h4>
<p class="news-details">{% highlight one_news.digest with query %}</p>
<div class="news-other">
<span class="news-type">{{ one_news.object.tag.name }}</span>
<span class="news-time">{{ one_news.object.update_time }}</span>
<span
class="news-author">{% highlight one_news.object.author.username with query %}
</span>
</div>
</div>
</li>
{% endfor %}
</ul>
</div>
{% else %}
<div class="news-contain">
<div class="hot-recommend-list">
<h2 class="hot-recommend-title">熱門推薦</h2>
<ul class="news-list">
{% for one_hotnews in page.object_list %}
<li class="news-item clearfix">
<a href="#" class="news-thumbnail">
<img src="{{ one_hotnews.news.image_url }}">
</a>
<div class="news-content">
<h4 class="news-title">
<a href="{% url 'news:detail' one_hotnews.news.id %}">{{ one_hotnews.news.title }}</a>
</h4>
<p class="news-details">{{ one_hotnews.news.digest }}</p>
<div class="news-other">
<span class="news-type">{{ one_hotnews.news.tag.name }}</span>
<span class="news-time">{{ one_hotnews.update_time }}</span>
<span class="news-author">{{ one_hotnews.news.author.username }}</span>
</div>
</div>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endif %}
<!-- search-list end -->
<!-- news-contain start -->
{# 分頁導航 #}
<div class="page-box" id="pages">
<div class="pagebar" id="pageBar">
<a class="a1">{{ page.paginator.count }}條</a>
{# 上一頁的URL地址 #}
{% if page.has_previous %}
{% if query %}
<a href="{% url 'news:search' %}?q={{ query }}&page={{ page.previous_page_number }}"
class="prev">上一頁</a>
{% else %}
<a href="{% url 'news:search' %}?page={{ page.previous_page_number }}" class="prev">上一頁</a>
{% endif %}
{% endif %}
{# 列出所有的URL地址 #}
{% for num in page.paginator.page_range|slice:":10" %}
{% if num == page.number %}
<span class="sel">{{ page.number }}</span>
{% else %}
{% if query %}
<a href="{% url 'news:search' %}?q={{ query }}&page={{ num }}"
target="_self">{{ num }}</a>
{% else %}
<a href="{% url 'news:search' %}?page={{ num }}" target="_self">{{ num }}</a>
{% endif %}
{% endif %}
{% endfor %}
{# 如果頁數大於10,則打兩點 #}
{% if page.paginator.num_pages > 10 %}
..
{% if query %}
<a href="{% url 'news:search' %}?q={{ query }}&page={{ page.paginator.num_pages }}"
target="_self">{{ page.paginator.num_pages }}</a>
{% else %}
<a href="{% url 'news:search' %}?page={{ page.paginator.num_pages }}"
target="_self">{{ page.paginator.num_pages }}</a>
{% endif %}
{% endif %}
{# 下一頁的URL地址 #}
{% if page.has_next %}
{% if query %}
<a href="{% url 'news:search' %}?q={{ query }}&page={{ page.next_page_number }}"
class="next">下一頁</a>
{% else %}
<a href="{% url 'news:search' %}?page={{ page.next_page_number }}"
class="next">下一頁</a>
{% endif %}
{% endif %}
</div>
</div>
<!-- news-contain end -->
</div>
7-4:高亮及分頁樣式
/* === current index start === */
#pages {
padding: 32px 0 10px;
}
.page-box {
text-align: center;
/*font-size: 14px;*/
}
#pages a.prev, a.next {
width: 56px;
padding: 0
}
#pages a {
display: inline-block;
height: 26px;
line-height: 26px;
background: #fff;
border: 1px solid #e3e3e3;
text-align: center;
color: #333;
padding: 0 10px
}
#pages .sel {
display: inline-block;
height: 26px;
line-height: 26px;
background: #0093E9;
border: 1px solid #0093E9;
color: #fff;
text-align: center;
padding: 0 10px
}
.highlighted{
color:coral;
mso-ansi-font-weight: bold;
}
/* === current index end === */
8:效果圖

