search: add possibility to specify templates for hits (#25614)

This commit is contained in:
Frédéric Péters 2018-08-09 10:31:20 +02:00
parent 90a11b1328
commit 1b6a015539
3 changed files with 56 additions and 0 deletions

View File

@ -29,3 +29,16 @@ which is sent to template 'combo/search-cell-results.html'
If the cell slug is "foo" and a variable named "foo" exists in the
query_string, it is added to the global page context, so it can be
used, for example, by a JsonCell.
It is also possible to extend the search service definition with custom
templates for hit URLs and labels:
COMBO_SEARCH_SERVICES = {
'user': {
'label': 'Search a user',
'url': 'https://.../api/user/?q=%(q)s',
'hit_url_template': '/fiche-usager/{{user_name_identifier_0}}/',
'hit_label_template': '{{first_name}} {{last_name}}',
},
}

View File

@ -21,6 +21,7 @@ from django.http import HttpResponse
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.utils.http import quote
from django.template import Context, Template
from jsonfield import JSONField
@ -140,4 +141,15 @@ class SearchCell(CellBase):
kwargs['cache_duration'] = service.get('cache_duration', 0)
kwargs['remote_service'] = 'auto' if service.get('signature') else None
results = requests.get(url, **kwargs).json()
hit_templates = {}
if service.get('hit_url_template'):
hit_templates['url'] = Template(service['hit_url_template'])
if service.get('hit_label_template'):
hit_templates['text'] = Template(service['hit_label_template'])
if service.get('hit_description_template'):
hit_templates['description'] = Template(service['hit_description_template'])
if hit_templates:
for hit in results.get('data') or []:
for k, v in hit_templates.items():
hit[k] = v.render(Context(hit))
return render_response(service, results)

View File

@ -138,6 +138,37 @@ def test_search_global_context(app):
resp = app.get(url)
assert requests_get.call_args[0][0] == 'http://www.example.net/search/foo/'
def test_search_custom_templates(app):
services = {
'search2': {
'label': 'Search 2',
'url': 'http://www.example.net/search/?q=%(q)s',
'hit_url_template': 'http://example.net/{{id}}/',
'hit_label_template': '{{a}} {{b}}',
'hit_description_template': 'description {{a}}',
}
}
with SearchServices(services):
page = Page(title='Search', slug='search_page', template_name='standard')
page.save()
cell = SearchCell(page=page, placeholder='content', order=0)
cell._search_services = {'data': ['search2']}
cell.save()
with mock.patch('combo.apps.search.models.requests.get') as requests_get:
response = {
'err': 0,
'data': [{'id': '123', 'a': 'A', 'b': 'B'}],
}
mock_json = mock.Mock()
mock_json.json.return_value = response
requests_get.return_value = mock_json
resp = app.get('/ajax/search/%s/search2/?q=foo' % cell.pk, status=200)
assert resp.text.count('<li>') == 1
assert '<li><a href="http://example.net/123/">A B</a>' in resp.text
assert '<div>description A</div>' in resp.text
def test_search_cell_visibility(app):
page = Page(title='example page', slug='example-page')