专栏首页毛利学PythonDjango项目知识点(五)

Django项目知识点(五)

搜索

谈搜索,不得不提es,全名 Elasticsearch。

自行实现django框架和全文检索引擎的代码比较麻烦,抱着不重复造轮子的原则。

选用django的第三方包djangohaystack。它支持多种全文检索引擎,本项目选择最流行的全文检索引擎之一elasticsearch。

安装elasticsearch很艰难,推荐使用docker,不要安装windows,会强制下载VirtualBox会与vm冲突的

docker

什么是docker?

  • 简化创建,部署,运行应用程序的一个工具
  • 打包应用程序所需的库和依赖环境
  • 精简的虚拟机

docker vs 虚拟机

安装

https://docs.docker.com/install/

  • 版本 ce和ee

Docker Engine改为Docker CE(社区版)

Docker Data Center改为Docker EE(企业版)

下面是ubuntu下安装(来源官网)

如果是第一次安装,你需要先添加docker的源然后再安装

  1. 更新包
$ sudo apt-get update
  1. 安装证书
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
  1. 添加docker的官方GPGkey
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
  1. 添加docker源
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

安装 docker ce

  1. 更新包索引
$ sudo apt-get update
  1. 安装docker
$ sudo apt-get install docker-ce
  1. 检测是否安装成功
$ sudo docker run hello-world

安装成功会出现如下输出:Hello from Docker!

先镜像加速,不然你会怀疑人生的

编辑文件/etc/docker/daemon.json,没有就新建。加入以下项目

下面的源可以改掉

{
    "registry-mirrors": ["https://registry.docker-cn.com","http://hub-mirror.c.163.com"]
}


{
  "registry-mirrors": ["https://nelhtz00.mirror.aliyuncs.com"]
}

镜像和容器的概念

就像类和实例的类,镜像就是类,容器就是对象

补充docker命令

去docker 官方下载 Shell docker pull <name>:16.04

运行镜像文件。

docker run -i -t
docker run <image-id>
docker run -p <port1>:<port2> <name>

查看镜像文件。

docker image ls
docker images

删除镜像文件。

docker rmi <name>
docker rmi fce289e99eb9 -f

查看正在运行容器。

docker ps

停止运行的容器。

docker stop <container-id>
docker stop <name>

对于那些不会自动终止的容器,就可以用下面的方式来停止。

docker container kill <container-id>

吹了那些多docker,连es都没吹

搜索功能环境搭建

docker的镜像:https://hub.docker.com/

注意:因为haystack目前支持的elasticsearch版本为 1.x和2.x

所以这里选择2.4.6

$ docker pull elasticsearch:2.4.6

但是外国人开发的,所以安装中文分词插件elasticsearch-ik,不安装分不了中文词,搜不了中文

下载es-ik后,将其解压到名为ik的文件夹

~$ unzip elasticsearch-analysis-ik-1.10.6.zip -d ./ik

ik所在文件下创建名为Dockerfile的文件,内容如下

FROM    elasticsearch:2.4.6
MAINTAINER    Fisher ""  你下载docker注册的邮箱  名字@邮箱
ADD     ./ik/ /usr/share/elasticsearch/plugins/ik/  

将Dockerfile同步在ubuntu

sudo docker build -t  你的名字/els-ik:2.4.6 .

运行成功后,会在你的docker中创建一个新的镜像叫做 你的名字/els-ik

最后运行curl命令检测es是否正常

~$ curl http://127.0.0.1:9200
{
  "name" : "Shard",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "Pq6BQQhTQN6q6ML6ThPlbw",
  "version" : {
    "number" : "2.4.6",
    "build_hash" : "5376dca9f70f3abef96a77f4bb22720ace8240fd",
    "build_timestamp" : "2017-07-18T12:17:44Z",
    "build_snapshot" : false,
    "lucene_version" : "5.5.4"
  },
  "tagline" : "You Know, for Search"
}

djangohaystack

pip install django-haystack
  • settings.py

添加'haystack'

INSTALLED_APPS = [
    # 'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'haystack',
]

补充settings.py

HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
        'URL': 'http://127.0.0.1:9200/',    # 此处为elasticsearch运行的服务器ip地址和端口
        'INDEX_NAME': '',           # 指定elasticserach建立的索引库名称
    },
}
# 搜索结果每页显示数量
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 5
# 实时更新index
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

haystack操作es还需要python的es驱动。

官网 :https://github.com/elastic/elasticsearch-py

pip install elasticsearch==2.4.1

至此,环境搭建完成。相对应的es,es-ik,haystack,es-python的版本请保持一致。django支持2.x版本,es到了7.x版本

使用

下面代码来源项目,无需看懂,知道怎么搞就可以了

在需要搜索的app,创建search_indexes.py文件

创建haystack数据模型

from haystack import indexes
from .models import News


class NewsIndex(indexes.SearchIndex, indexes.Indexable):
    """
    这个模型的作用类似django的模型,它告诉haystack哪些数据会被
    放进查询回的模型对象中,以及通过哪些字段进行索引和查询
    """
    # 这字段必须这么写,用来告诉haystack和搜索引擎要索引哪些字段
    text = indexes.CharField(document=True, use_template=True)
    id = indexes.CharField(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:
        """
        return News

    def index_queryset(self, using=None):
        """
        返回要建立索引的数据查询集
        :param using:
        :return:
        """
        return self.get_model().objects.filter(is_delete=False)

创建索引数据模板

  1. 在templates中创建文件search/indexes/yourappname/modelname_text.txt,所以本项目需要创建search/indexes/news/news_text.txt,文件内容如下:
   {{ object.title }}
   {{ object.digest }}
   {{ object.content }}
   {{ object.author.username }}
  1. 创建索引 按上面的步骤配置好后,就可以运行haystack的命令创建索引了 ~$ python manage.py rebuild_index
  2. 视图编写
from haystack.generic_views import SearchView

class NewsSearchView(SearchView):
    """
    新闻搜索视图
    """
    # 设置搜索模板文件
    template_name = 'news/search.html'

    # 重写get请求,如果请求参数q为空,返回模型News的热门新闻数据
    # 否则根据参数q搜索相关数据
    def get(self, request, *args, **kwargs):
        query = request.GET.get('q')
        if not query:
            # 显示热门新闻
            hot_news = HotNews.objects.select_related('news__tag').only('news__title', 'news__image_url', 'news_id',
                                                                        'news__tag__name').filter(
                is_delete=False).order_by('priority', '-news__clicks')
            paginator = Paginator(hot_news, settings.HAYSTACK_SEARCH_RESULTS_PER_PAGE)
            try:
                page = paginator.get_page(int(request.GET.get('page')))
            except Exception as e:
                page = paginator.get_page(1)

            return render(request, 'news/search.html', context={
                'page': page,
                'paginator': paginator,
                'query': query
            })
        else:
            # 搜索
            return super().get(request, *args, **kwargs)

    def get_context_data(self, *args, **kwargs):
        """
        在context中添加page变量
        :param args: 
        :param kwargs: 
        :return: 
        """
        context = super().get_context_data(*args, **kwargs)
        if context['page_obj']:
            context['page'] = context['page_obj']
        return context

路由

在news/urls.py中添加如下路由

   path('news/search/', views.NewsSearchView.as_view(), name='news_search')

学不死,就往死里学。

本文分享自微信公众号 - 毛利学Python(sen13717378202)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Selenium抓取HTTPS请求

    Selenium本身是不支持HTTP和HTTPS请求抓取的,因为其团队认为这个不是selenium要解决的问题(确实也是)。所以推荐使用一个相关联的项目 -- ...

    上帝De助手
  • joda-time使用教程

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    suveng
  • Serverless实践系列(九):“灰常”简单的车牌识别 API 制作

    本文的真正目的,其实并非要做一个完善的车牌识别工具,而是想要通过一些简单的 package 组合(包括深度学习框架等),实现一个简单的对外接口,用它来进行车牌...

    腾讯云serverless团队
  • python3下常用编解码与加解密

    Python3相对于Python2的一大改变就是,对默认字符类型进行了修改。Python2中定义字符串默认为二进制字符串,强制加前缀u的才是unicode字符串...

    上帝De助手
  • python的异常处理

    原文链接:https://www.runoob.com/python/python-exceptions.html

    于小勇
  • 文末送书 | Python的高级特征你知多少?

    开篇先说,IEEE Spectrum 于9月6日发布了2019年最受欢迎的编程语言排名,无疑Python蝉联第一,成绩颇为亮眼。从前年开始,Python 就开始...

    用户1737318
  • tf.convert_to_tensor

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    于小勇
  • python的命名空间

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    于小勇
  • Python语法糖系列

    简而言之,语法糖就是程序语言中提供[奇技淫巧]的一种手段和方式而已。 通过这类方式编写出来的代码,即好看又好用,好似糖一般的语法。固美其名曰:语法糖

    上帝De助手
  • Python各种类型装饰器详解说明

    相信通过上述一段文字的描述,大家应该更加的迷惑了!所以下面我们就结合代码来理解Python中的装饰器。

    上帝De助手

扫码关注云+社区

领取腾讯云代金券