From 5916069c4120d98d33149b2898f5b764a2dde540 Mon Sep 17 00:00:00 2001 From: Drew Larson Date: Wed, 1 Jun 2016 21:04:22 -0600 Subject: [PATCH 1/3] Add haystack and whoosh. --- requirements/base.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/requirements/base.txt b/requirements/base.txt index edb5239..65f86f8 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -4,4 +4,6 @@ django-widget-tweaks==1.4.1 psycopg2==2.6.1 django-libsass==0.6 django_compressor==2.0 -python-dateutil==2.5.3 \ No newline at end of file +python-dateutil==2.5.3 +whoosh==2.7.4 +git+git://github.com/django-haystack/django-haystack.git \ No newline at end of file From 8036e47c61f0d95bfcaab86ae03d7b403d0aa547 Mon Sep 17 00:00:00 2001 From: Drew Larson Date: Wed, 1 Jun 2016 21:05:02 -0600 Subject: [PATCH 2/3] Add haystack to django. --- bikeshop_project/bikeshop/settings/base.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/bikeshop_project/bikeshop/settings/base.py b/bikeshop_project/bikeshop/settings/base.py index 6d32945..9982cf9 100644 --- a/bikeshop_project/bikeshop/settings/base.py +++ b/bikeshop_project/bikeshop/settings/base.py @@ -29,7 +29,7 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - + 'haystack', 'webpack_loader', 'compressor', @@ -142,4 +142,11 @@ WEBPACK_LOADER = { 'POLL_INTERVAL': 0.1, 'IGNORE': ['.+\.hot-update.js', '.+\.map'] } +} + +HAYSTACK_CONNECTIONS = { + 'default': { + 'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine', + 'PATH': os.path.join(os.path.dirname(__file__), 'whoosh_index'), + }, } \ No newline at end of file From 99cd30ec253bf847d43d640035d86119d683d4ec Mon Sep 17 00:00:00 2001 From: Drew Larson Date: Wed, 1 Jun 2016 21:05:26 -0600 Subject: [PATCH 3/3] Basic search endpoint. --- .../registration/search_indexes.py | 9 ++++++++ .../indexes/registration/member_text.txt | 2 ++ bikeshop_project/registration/urls.py | 3 ++- bikeshop_project/registration/views.py | 21 ++++++++++++++++--- 4 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 bikeshop_project/registration/search_indexes.py create mode 100644 bikeshop_project/registration/templates/search/indexes/registration/member_text.txt diff --git a/bikeshop_project/registration/search_indexes.py b/bikeshop_project/registration/search_indexes.py new file mode 100644 index 0000000..ad20429 --- /dev/null +++ b/bikeshop_project/registration/search_indexes.py @@ -0,0 +1,9 @@ +from haystack import indexes +from .models import Member + + +class MemberIndex(indexes.SearchIndex, indexes.Indexable): + text = indexes.EdgeNgramField(document=True, use_template=True) + + def get_model(self): + return Member diff --git a/bikeshop_project/registration/templates/search/indexes/registration/member_text.txt b/bikeshop_project/registration/templates/search/indexes/registration/member_text.txt new file mode 100644 index 0000000..1c75611 --- /dev/null +++ b/bikeshop_project/registration/templates/search/indexes/registration/member_text.txt @@ -0,0 +1,2 @@ +{{ object.email }} +{{ object.get_full_name }} \ No newline at end of file diff --git a/bikeshop_project/registration/urls.py b/bikeshop_project/registration/urls.py index 07024cb..c345e7f 100644 --- a/bikeshop_project/registration/urls.py +++ b/bikeshop_project/registration/urls.py @@ -1,7 +1,8 @@ from django.conf.urls import url -from .views import MemberFormView +from .views import MemberFormView, MemberSearchView urlpatterns = [ url(r'^new/$', MemberFormView.as_view(), name='signup'), + url(r'^search/(?P[\w@\.\+]+)/$', MemberSearchView.as_view(), name='member_search'), url(r'^edit/(?P[0-9]+)/$', MemberFormView.as_view(), name='member_edit') ] diff --git a/bikeshop_project/registration/views.py b/bikeshop_project/registration/views.py index 3d1f983..99de29a 100644 --- a/bikeshop_project/registration/views.py +++ b/bikeshop_project/registration/views.py @@ -1,12 +1,17 @@ +import logging + from django.contrib import messages -from django.http import HttpResponseRedirect +from django.core.urlresolvers import reverse +from django.http import HttpResponse, HttpResponseRedirect from django.template.response import TemplateResponse from django.views.generic import View -from django.core.urlresolvers import reverse + +import json +from haystack.query import SearchQuerySet from .forms import MemberForm from .models import Member -import logging + logger = logging.getLogger('bikeshop') @@ -46,3 +51,13 @@ class MemberFormView(View): if member: context['member'] = member return TemplateResponse(request, 'member_form.html', context=context) + + +class MemberSearchView(View): + def get(self, request, query): + sqs = SearchQuerySet().models(Member).autocomplete(text=query)[:5] + results = [dict(name=result.object.get_full_name(), email=result.object.email, id=result.object.id) for result in sqs] + + data = json.dumps(dict(results=results)) + + return HttpResponse(data, content_type='application/json') \ No newline at end of file