Implement multi-model search

pull/20/head
Scot Hacker 2017-02-10 13:05:54 +00:00
rodzic 3e5ce066f8
commit 293a740f1f
11 zmienionych plików z 138 dodań i 6 usunięć

Wyświetl plik

@ -44,6 +44,11 @@ class People(ClusterableModel):
ImageChooserPanel('image')
]
search_fields = Page.search_fields + [
index.SearchField('first_name'),
index.SearchField('last_name'),
]
def __str__(self):
return self.first_name + " " + self.last_name

Wyświetl plik

@ -19,7 +19,7 @@ from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
from wagtail.wagtailcore.fields import StreamField
from wagtail.wagtailcore.models import Page, Orderable
from wagtail.wagtailsnippets.edit_handlers import SnippetChooserPanel
from wagtail.wagtailsearch import index
from bakerydemo.base.blocks import BaseStreamBlock
@ -75,6 +75,11 @@ class BlogPage(Page):
FieldPanel('tags'),
]
search_fields = Page.search_fields + [
index.SearchField('title'),
index.SearchField('body'),
]
def authors(self):
'''
Returns the BlogPage's related People

Wyświetl plik

@ -111,7 +111,7 @@ class LocationPage(Page):
]
def __str__(self):
return self.name
return self.title
def opening_hours(self):
hours = self.hours_of_operation.all()

Wyświetl plik

@ -0,0 +1,58 @@
from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from wagtail.wagtailcore.models import Page
from wagtail.wagtailsearch.models import Query
from bakerydemo.blog.models import BlogPage
from bakerydemo.breads.models import BreadPage
from bakerydemo.locations.models import LocationPage
from bakerydemo.base.models import People
def search(request):
# Search
search_query = request.GET.get('query', None)
if search_query:
'''
Because we can't use ElasticSearch for the demo, we use the native db search.
But native DB search can't search specific fields in our models on a `Page` query.
So for demo purposes ONLY, we hard-code in the model names we want to search.
In production, use ElasticSearch and a simplified search query, per
http://docs.wagtail.io/en/v1.8.1/topics/search/searching.html
'''
blog_results = BlogPage.objects.live().search(search_query)
blog_page_ids = [p.page_ptr.id for p in blog_results]
bread_results = BreadPage.objects.live().search(search_query)
bread_page_ids = [p.page_ptr.id for p in bread_results]
location_results = LocationPage.objects.live().search(search_query)
location_result_ids = [p.page_ptr.id for p in location_results]
page_ids = blog_page_ids + bread_page_ids + location_result_ids
search_results = Page.objects.live().filter(id__in=page_ids)
query = Query.get(search_query)
# Record hit
query.add_hit()
else:
search_results = Page.objects.none()
# Pagination
page = request.GET.get('page', 1)
paginator = Paginator(search_results, 10)
try:
search_results = paginator.page(page)
except PageNotAnInteger:
search_results = paginator.page(1)
except EmptyPage:
search_results = paginator.page(paginator.num_pages)
return render(request, 'search/search_results.html', {
'search_query': search_query,
'search_results': search_results,
})

Wyświetl plik

@ -35,7 +35,7 @@ INSTALLED_APPS = [
'bakerydemo.blog',
'bakerydemo.breads',
'bakerydemo.locations',
# 'bakerydemo.search',
'bakerydemo.search',
'wagtail.contrib.wagtailsearchpromotions',
'wagtail.wagtailforms',
@ -168,6 +168,7 @@ WAGTAILSEARCH_BACKENDS = {
},
}
# Wagtail settings
WAGTAIL_SITE_NAME = "bakerydemo"

Wyświetl plik

@ -20,7 +20,7 @@
{% endif %}
{% endblock %}
</title>
<meta name="description" content="">
<meta name="description" content="{% if self.search_description %}{{ self.search_description }}{% endif %}">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap Core CSS -->
@ -65,6 +65,11 @@
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li>
{% block search_box %}
{% include "search/search_box.html" only %}
{% endblock %}
</li>
<li>
<a href="index.html">Home</a>
</li>
@ -77,6 +82,8 @@
<li>
<a href="contact.html">Contact</a>
</li>
</ul>
</div>
<!-- /.navbar-collapse -->

Wyświetl plik

@ -0,0 +1,14 @@
<form action="{% url 'search' %}" class="form-inline" method="get">
<div class="row">
<div class="col-sm-12">
<div class="input-group">
<input type="text" name="query" class="form-control" />
<div class="input-group-btn">
<button type="submit" class="btn btn-primary">
<i class="glyphicon glyphicon-search"></i> Search
</button>
</div>
</div>
</div>
</div>
</form>

Wyświetl plik

@ -0,0 +1,34 @@
{% extends "base.html" %}
{% load wagtailcore_tags %}
{% block title %}Search{% if search_results %} results{% endif %}{% endblock %}
{% block content %}
<h1>
Search results{% if request.GET.query %} for “{{ request.GET.query }}”{% endif %}
</h1>
{% if search_results %}
<ul>
{% for result in search_results %}
<li>
<h4>
{% if result.specific.content_type.model == "blogpage" %}
Blog post:
{% elif result.specific.content_type.model == "locationpage" %}
Location:
{% else %}
Bread
{% endif %}
<a href="{% pageurl result.specific %}">{{ result.specific }}</a>
</h4>
{% if result.specific.search_description %}{{ result.specific.search_description|safe }}{% endif %}
</li>
{% endfor %}
</ul>
{% elif search_query %}
No results found
{% else %}
You didnt search for anything!
{% endif %}
{% endblock %}

Wyświetl plik

@ -6,7 +6,7 @@ from wagtail.wagtailadmin import urls as wagtailadmin_urls
from wagtail.wagtaildocs import urls as wagtaildocs_urls
from wagtail.wagtailcore import urls as wagtail_urls
# from bakerydemo.search import views as search_views
from bakerydemo.search import views as search_views
urlpatterns = [
@ -15,7 +15,7 @@ urlpatterns = [
url(r'^admin/', include(wagtailadmin_urls)),
url(r'^documents/', include(wagtaildocs_urls)),
# url(r'^search/$', search_views.search, name='search'),
url(r'^search/$', search_views.search, name='search'),
]

Wyświetl plik

@ -46,3 +46,11 @@ With PIP installed run the following commands:
./manage.py load_initial_data
./manage.py createsuperuser
./manage.py runserver
### Note on demo search:
Because we can't (easily) use ElasticSearch for this demo, we use wagtail's native DB search.
However, native DB search can't search specific fields in our models on a generalized `Page` query.
So for demo purposes ONLY, we hard-code the model names we want to search into `search.views`, which is
not ideal. In production, use ElasticSearch and a simplified search query, per
http://docs.wagtail.io/en/v1.8.1/topics/search/searching.html