Django REST Elasticsearch:Django集成ES
目录
Django REST Elasticsearch简介
Django REST Elasticsearch提供了集成Django REST Framework和Elasticsearch的简便方法。该库使用Elasticsearch DSL库(elasticsearch-dsl-py)它是官方低级客户端的高级库。
让我们看一下使用Django REST Elasticsearch构建一个简单应用程序的快速示例。在这个例子中,我们将构建一个简单的博客系统。
要求
- Django REST Framework 3.5及更高版本
- elasticsearch-dsl> = 5.0.0,<7.0.0(Elasticsearch 5.x)
操作步骤
安装
pip3 install django-rest-elasticsearch -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com
创建项目
[root@localhost ~]# django-admin startproject tutorial
[root@localhost ~]# ls
anaconda-ks.cfg CentOS-Sources.repo jdk1.8.0_211 apache-maven-3.5.4-bin.tar.gz centos.tar jdk-8u211-linux-x64.tar.gz big_data CentOS-Vault.repo mongodb-linux-x86_64-rhel62-4.0.0.tgz CentOS-Base.repo docker-ce.repo Python-3.6.5 CentOS-CR.repo Dockerfile Python-3.6.5.tgz CentOS-Debuginfo.repo elasticsearch-5.5.1 tutorial CentOS-fasttrack.repo elasticsearch-5.5.1.zip CentOS-Media.repo HelloWorld
创建APP
[root@localhost ~]# cd tutorial
[root@localhost tutorial]# python3 manage.py startapp blog
配置APP
在tutorial/settings.py 中添加APP:
[root@localhost tutorial]# vi settings.py
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'blog', ]
配置URL
在tutorial/urls.py中配置URL:
from django.contrib import admin from django.urls import path from django.conf.urls import include urlpatterns = [ path('admin/', admin.site.urls), path('blog/', include('blog.urls')), ]
编写内部路由文件:
blog/urls.py:
from django.conf.urls import url from . import views urlpatterns = [ ]
创建模型
blog/models.py:
from django.db import models from django.utils.translation import ugettext_lazy as _ from django.contrib.postgres.fields import ArrayField # Create your models here. class Blog(models.Model): title = models.CharField(_('Title'), max_length=1000) #博客题目 created_at = models.DateTimeField(_('Created at'), auto_now_add=True) #创建日期 body = models.TextField(_('Body'))#博客正文 tags = ArrayField(models.CharField(max_length=200), blank=True, null=True) #博客标签 is_published = models.BooleanField(_('Is published'), default=False) #是否公开 def __str__(self): return self.title
在ES中创建映射
创建一个 DocType 来代表我们的博客模型
blog/search_indexes.py:
from elasticsearch_dsl import DocType,Date, Integer, Keyword, Text,Boolean from elasticsearch_dsl.connections import connections # Define a default Elasticsearch client connections.create_connection(hosts=['localhost']) class BlogIndex(DocType): pk = Integer() title = Text(fields={'raw': Keyword()}) created_at = Date() body = Text() tags = Keyword(multi=True) is_published = Boolean() class Meta: index = 'blog' # 在Elasticsearch中创建映射 #我们需要在Elasticsearch中创建映射。这里通过调用init类方法直接创建映射: if __name__ == "__main__": BlogIndex.init()
在命令行中执行此程序 python3 search_indexes.py
然后,运行curl命令检验一下,
看看ES中是否新建了索引blog:
[root@localhost blog]# curl -X GET 'http://localhost:9200/_cat/indices?v'
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size ... yellow open blog 4VV7_m7bT-aarL7URl2XzQ 5 1 0 0 810b 810b ...
‘在ES创建映射’这一部分的代码,跟普通Django REST framework 项目中的数据库迁移命令( python3 manage.py migrate )很相似,只不过现在面对的“数据库”是我们的Elasticsearch。
另:在文档生命周期文档中,您可以找到有关如何手动使用文档的完整说明。
网络配置
配置连接ES的实例:
blog/config.py:
from elasticsearch import Elasticsearch, RequestsHttpConnection es_client = Elasticsearch( hosts=['10.0.0.30:9200/'], connection_class=RequestsHttpConnection )
编写序列化模块
使用 Serializer 可以将 queryset, model 实例等复杂数据类型(complex types)序列化成原生的 python 数据结构,且将其渲染成 JSON,XML 等其他数据类型。 Serializers 也可以反序列化,可将输入数据验证后,解析成复杂数据类型。
blog/serializers.py :
from rest_framework_elasticsearch.es_serializer import ElasticModelSerializer from .models import Blog from .search_indexes import BlogIndex class ElasticBlogSerializer(ElasticModelSerializer): class Meta: model = Blog es_model = BlogIndex fields = ('pk', 'title', 'created_at', 'tags', 'body', 'is_published')
添加信号调度程序
(作用:添加,更新或删除新数据时使索引可更新)
我们希望在ElasticSearch中拥有一致的数据,这就是我们在更改模型中的任何内容时需要创建,更新或删除文档的原因。最好的方法是添加一个Django信号调度程序。在添加信号之前,我们上一步已经创建了一个序列化器来创建,更新和删除elasticsearch文档。
现在,我们需要创建signals.py文件:
from .config import es_client from django.db.models.signals import pre_save, post_delete from django.dispatch import receiver from .serializers import Blog, ElasticBlogSerializer @receiver(pre_save, sender=Blog, dispatch_uid="update_record") def update_es_record(sender, instance, **kwargs): obj = ElasticBlogSerializer(instance) obj.save(using=es_client) @receiver(post_delete, sender=Blog, dispatch_uid="delete_record") def delete_es_record(sender, instance, *args, **kwargs): obj = ElasticBlogSerializer(instance) obj.delete(using=es_client, ignore=404)
加载signals设置: blog/ __init__.py中填写:
default_app_config = 'blog.apps.BlogConfig'
在blog/apps.py中重写ready方法:
from django.apps import AppConfig class BlogConfig(AppConfig): name = 'blog' def ready(self): import blog.signals # noqa
解释: 当INSTALLED_APPS 包含一个应用模块的路径后,Django 将在这个模块中检查一个default_app_config 变量。如果这个变量有定义,它应该是这个应用的AppConfig 子类的路径,调用get_app_config返回的是这个子类化的AppConfig。如果没有default_app_config,Django 将使用AppConfig 基类,调用get_app_config返回的是AppConfig基类。(https://blog.csdn.net/weixin_34268169/article/details/94320415)
参考文档:https://www.jianshu.com/p/4f1bf0905c69
编写视图
最后,让我们创建一个简单的搜索视图,查找按标签过滤的所有帖子,并按标题中的单词进行搜索:
blog/views.py:
#from config.es_client import es_client from .config import es_client from rest_framework_elasticsearch import es_views, es_pagination, es_filters from .search_indexes import BlogIndex class BlogView(es_views.ListElasticAPIView): es_client = es_client es_model = BlogIndex es_pagination_class = es_pagination.ElasticLimitOffsetPagination es_filter_backends = ( es_filters.ElasticFieldsFilter, es_filters.ElasticSearchFilter, es_filters.ElasticOrderingFilter, ) es_ordering_fields = ( "created_at", ("title.raw", "title") ) es_filter_fields = ( es_filters.ESFieldFilter('tag', 'tags'), es_filters.ESFieldFilter('is_published', 'is_published') ) es_search_fields = ( 'tags', 'title', )
编写路由
blog/urls.py:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^api/list$', views.BlogView.as_view(), name='blog-list'), ]
模型注册
Django自带的后台管理是Django明显特色之一,可以让我们快速便捷管理数据。后台管理可以在各个app的admin.py文件中进行控制。
blog/admin.py
from django.contrib import admin # Register your models here. from django.contrib import admin from .models import Blog @admin.register(Blog) class GalleryCategoryAdmin(admin.ModelAdmin): list_display = ('title', 'is_published')
测试
curl http://10.0.0.30:8000/blog/api/list?search=elasticsearch
curl http://10.0.0.30:8000/blog/api/list?tag=opensource
curl http://10.0.0.30:8000/blog/api/list?tag=opensource,aws
或直接在浏览器上打开:
参考文档:
[1] https://www.jianshu.com/p/cd3d60da3128
[2] https://www.helplib.com/GitHub/article_154027
[3]https://github.com/myarik/django-rest-elasticsearch
[4] https://www.jianshu.com/p/7179229eeac1
[5] https://blog.csdn.net/weixin_34018169/article/details/88469999