add internal page contents search service (#6793)
This commit is contained in:
parent
63f6794e8b
commit
6491f69cd1
|
@ -20,6 +20,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||
from django import template
|
||||
from django.http import HttpResponse
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.forms import models as model_forms, Select
|
||||
from django.utils.http import quote
|
||||
|
||||
|
@ -37,15 +38,14 @@ class SearchCell(CellBase):
|
|||
class Meta:
|
||||
verbose_name = _('Search')
|
||||
|
||||
@classmethod
|
||||
def is_enabled(cls):
|
||||
return bool(getattr(settings, 'COMBO_SEARCH_SERVICES', {}))
|
||||
|
||||
def is_visible(self, user=None):
|
||||
if not self.search_service:
|
||||
return False
|
||||
return super(SearchCell, self).is_visible(user=user)
|
||||
|
||||
def get_default_form_class(self):
|
||||
search_services = [(None, _('Not configured'))]
|
||||
search_services.append(('_text', _('Page Contents')))
|
||||
search_services.extend([(code, service['label'])
|
||||
for code, service in getattr(settings, 'COMBO_SEARCH_SERVICES', {}).items()])
|
||||
widgets = {'_search_service': Select(choices=search_services)}
|
||||
|
@ -62,6 +62,8 @@ class SearchCell(CellBase):
|
|||
|
||||
@property
|
||||
def search_service(self):
|
||||
if self._search_service == '_text':
|
||||
return {'url': reverse('api-search') + '?q=%(q)s', 'label': _('Page Contents')}
|
||||
return settings.COMBO_SEARCH_SERVICES.get(self._search_service) or {}
|
||||
|
||||
def modify_global_context(self, context, request):
|
||||
|
@ -100,6 +102,8 @@ class SearchCell(CellBase):
|
|||
query = request.GET.get('q')
|
||||
if query and cell.search_service.get('url'):
|
||||
url = cell.search_service.get('url') % {'q': quote(query.encode('utf-8'))}
|
||||
if url.startswith('/'):
|
||||
url = request.build_absolute_uri(url)
|
||||
results = requests.get(url, cache_duration=0).json()
|
||||
else:
|
||||
results = {'err': 0, 'data': []}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<div class="links-list">
|
||||
<ul>
|
||||
{% for item in results.data %}
|
||||
<li><a href="{{ item.url }}">{{ item.text }}</a>{% if item.description %}
|
||||
{{ item.description|safe }}
|
||||
{% endif %}</li>
|
||||
<li><a href="{{ item.url }}">{{ item.text }}</a>
|
||||
{% if item.description %}<div>{{ item.description|safe }}</div>{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -20,6 +20,7 @@ from . import views
|
|||
|
||||
urlpatterns = patterns('combo.publicviews',
|
||||
url(r'^api/menu-badges/', views.menu_badges),
|
||||
url(r'^api/search/', views.api_search, name='api-search'),
|
||||
url(r'^ajax/cell/(?P<page_pk>\w+)/(?P<cell_reference>[\w_-]+)/$',
|
||||
views.ajax_page_cell, name='combo-public-ajax-page-cell'),
|
||||
(r'__style__/$', views.style),
|
||||
|
|
|
@ -38,12 +38,15 @@ else:
|
|||
from django.utils.translation import ugettext as _
|
||||
from django.forms.widgets import Media
|
||||
|
||||
from haystack.query import SearchQuerySet
|
||||
|
||||
if 'mellon' in settings.INSTALLED_APPS:
|
||||
from mellon.utils import get_idps
|
||||
else:
|
||||
get_idps = lambda: []
|
||||
|
||||
from combo.data.models import CellBase, Page, ParentContentCell, TextCell
|
||||
from combo.apps.search.models import SearchCell
|
||||
from combo import utils
|
||||
|
||||
|
||||
|
@ -342,3 +345,27 @@ def menu_badges(request):
|
|||
if badge:
|
||||
badges[cell.page_id] = badge
|
||||
return HttpResponse(json.dumps(badges))
|
||||
|
||||
|
||||
def api_search(request):
|
||||
for cell in SearchCell.objects.filter(_search_service='_text'):
|
||||
if not cell.is_visible(request.user):
|
||||
continue
|
||||
break
|
||||
else:
|
||||
raise Http404()
|
||||
query = request.GET.get('q') or ''
|
||||
searchqueryset = SearchQuerySet()
|
||||
sqs = searchqueryset.auto_query(query).highlight()
|
||||
sqs.load_all()
|
||||
hits = []
|
||||
for page in sqs:
|
||||
if page.highlighted['text']:
|
||||
description = '<p>%s</p>' % page.highlighted['text'][0]
|
||||
hits.append({
|
||||
'text': page.title,
|
||||
'url': page.url,
|
||||
'description': description,
|
||||
})
|
||||
|
||||
return HttpResponse(json.dumps({'data': hits}), content_type='application/json')
|
||||
|
|
|
@ -24,6 +24,9 @@ LINGO_SIGNATURE_KEY = '54321'
|
|||
import tempfile
|
||||
MEDIA_ROOT = tempfile.mkdtemp('combo-test')
|
||||
|
||||
HAYSTACK_CONNECTIONS['default']['PATH'] = os.path.join(
|
||||
tempfile.mkdtemp('combo-test-whoosh'))
|
||||
|
||||
if 'DISABLE_MIGRATIONS' in os.environ:
|
||||
class DisableMigrations(object):
|
||||
def __contains__(self, item):
|
||||
|
|
|
@ -36,13 +36,6 @@ class SearchServices(object):
|
|||
def __exit__(self, *args, **kwargs):
|
||||
delattr(settings, 'COMBO_SEARCH_SERVICES')
|
||||
|
||||
def test_enabled(app):
|
||||
assert SearchCell.is_enabled() == False
|
||||
with SearchServices(SEARCH_SERVICES):
|
||||
assert SearchCell.is_enabled() == True
|
||||
with SearchServices({}):
|
||||
assert SearchCell.is_enabled() == False
|
||||
|
||||
def test_search_cell(app):
|
||||
with SearchServices(SEARCH_SERVICES):
|
||||
page = Page(title='Search', slug='search_page', template_name='standard')
|
||||
|
@ -169,3 +162,38 @@ def test_search_contents_index():
|
|||
prepared_data = page_index.prepare(page)
|
||||
assert page.title in prepared_data['text']
|
||||
assert 'foobar' in prepared_data['text']
|
||||
|
||||
def test_search_api(app):
|
||||
page = Page(title='example page', slug='example-page')
|
||||
page.save()
|
||||
|
||||
cell = TextCell(page=page, text='<p>foobar baz</p>', order=0)
|
||||
cell.save()
|
||||
|
||||
second_page = Page(title='second page', slug='second-page')
|
||||
second_page.save()
|
||||
|
||||
cell = TextCell(page=second_page, text='<p>other baz</p>', order=0)
|
||||
cell.save()
|
||||
|
||||
page_index = PageIndex()
|
||||
page_index.reindex()
|
||||
|
||||
resp = app.get('/api/search/?q=foobar', status=404)
|
||||
|
||||
cell = SearchCell(page=page, _search_service='_text', order=0)
|
||||
cell.save()
|
||||
|
||||
resp = app.get('/api/search/?q=foobar', status=200)
|
||||
assert len(resp.json['data']) == 1
|
||||
assert resp.json['data'][0]['text'] == 'example page'
|
||||
|
||||
resp = app.get('/api/search/?q=other', status=200)
|
||||
assert len(resp.json['data']) == 1
|
||||
assert resp.json['data'][0]['text'] == 'second page'
|
||||
|
||||
resp = app.get('/api/search/?q=baz', status=200)
|
||||
assert len(resp.json['data']) == 2
|
||||
|
||||
resp = app.get('/api/search/?q=quux', status=200)
|
||||
assert len(resp.json['data']) == 0
|
||||
|
|
Loading…
Reference in New Issue