Skip to content

Commit

Permalink
add language support to ProductDocument
Browse files Browse the repository at this point in the history
  • Loading branch information
jrief committed Apr 29, 2020
1 parent d5ba07c commit 7fa2795
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 14 deletions.
1 change: 1 addition & 0 deletions shop/models/product.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from functools import reduce
import operator
from cms import __version__ as CMS_VERSION

from django.core import checks
from django.db import models
from django.db.models.aggregates import Sum
Expand Down
29 changes: 25 additions & 4 deletions shop/search/documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
from __future__ import unicode_literals

from django.template.loader import select_template
from django.utils import translation

from django_elasticsearch_dsl import fields, Document
from django_elasticsearch_dsl import fields, Document, Index
from elasticsearch_dsl import analyzer

from shop.models.product import ProductModel
Expand All @@ -17,7 +18,7 @@
)


class ProductDocument(Document):
class _ProductDocument(Document):
product_code = fields.KeywordField(
multi=True,
boost=5,
Expand Down Expand Up @@ -57,7 +58,6 @@ def prepare_body(self, instance):
Create a textual representation of the product's instance to be used by Elasticsearch for
creating a full text search index.
"""
print(f"------------ {instance.id}: {instance.product_model}")
app_label = instance._meta.app_label.lower()
params = [
(app_label, instance.product_model),
Expand All @@ -66,5 +66,26 @@ def prepare_body(self, instance):
]
template = select_template(['{0}/search/indexes/{1}.txt'.format(*p) for p in params])
body = template.render({'product': instance})
print(body)
return body

def update(self, thing, refresh=None, action='index', parallel=False, **kwargs):
with translation.override(self._language):
super().update(thing, refresh=None, action='index', parallel=False, **kwargs)


class ProductDocument:
def __new__(cls, language=None, settings=None, analyzer=None):
if language:
index_name = 'products-{}'.format(language.lower())
doc_name = 'ProductDocument{}'.format(language.title())
else:
index_name = 'products'
doc_name = 'ProductDocument'
products_index = Index(index_name)
if settings:
products_index.settings(**settings)
if analyzer:
products_index.analyzer(analyzer)
doc_class = type(doc_name, (_ProductDocument,), {'_language': language})
products_index.document(doc_class)
return doc_class
48 changes: 38 additions & 10 deletions shop/search/mixins.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
from shop.search.documents import ProductDocument
from django.utils.translation import get_language_from_request

from django_elasticsearch_dsl.registries import registry

from shop.models.product import ProductModel


class SearchViewMixin:
def get_queryset(self):
query = self.request.GET.get('q')
if query:
search = ProductDocument.search().source(excludes=['body'])
search = search.query('multi_match', query=query, fields=self.search_fields, type='bool_prefix')
queryset = search.to_queryset()
else:
queryset = super().get_queryset()
return queryset
def get_document(self, language):
documents = registry.get_documents([ProductModel])
try:
return next(doc for doc in documents if doc._language == language)
except StopIteration:
return next(doc for doc in documents if doc._language is None)


class ProductSearchViewMixin(SearchViewMixin):
"""
Mixin class to be added to the ProductListView so that autocompletion works.
"""
search_fields = ['product_name', 'product_code']

def get_renderer_context(self):
Expand All @@ -22,10 +26,34 @@ def get_renderer_context(self):
renderer_context['search_autocomplete'] = True
return renderer_context

def get_queryset(self):
query = self.request.GET.get('q')
if query:
language = get_language_from_request(self.request)
document = self.get_document(language)
search = document.search().source(excludes=['body'])
search = search.query('multi_match', query=query, fields=self.search_fields, type='bool_prefix')
queryset = search.to_queryset()
else:
queryset = super().get_queryset()
return queryset


class CatalogSearchViewMixin(SearchViewMixin):
"""
Mixin class to be added to the ProductListView in order to create a full-text search.
"""
search_fields = ['product_name', 'product_code', 'body']

def get_serializer(self, *args, **kwargs):
kwargs.setdefault('label', 'search')
return super().get_serializer(*args, **kwargs)

def get_queryset(self):
language = get_language_from_request(self.request)
document = self.get_document(language)
query = self.request.GET.get('q')
search = document.search().source(excludes=['body'])
if query:
search = search.query('multi_match', query=query, fields=self.search_fields)
return search.to_queryset()

0 comments on commit 7fa2795

Please sign in to comment.