[IMP] website(_*): replace search callbacks by a mixin

Before this commit the `_search_get_detail` result contained callback
functions to handle special behavior during fetching and rendering.

After this commit a `website.searchable.mixin` is introduced that must
be inherited by models that participate in website-based searches.
Custom behavior previously achieved with callbacks is now achieved by
overloading methods of this mixin.

task-2379555
https://github.com/odoo/odoo/pull/65871

Part-of: odoo/odoo#65871
This commit is contained in:
Benoit Socias
2021-09-03 06:59:33 +00:00
parent c6ba756e4b
commit 9f9c4bb7e4
11 changed files with 236 additions and 147 deletions
+1 -1
View File
@@ -551,7 +551,7 @@ class Website(Home):
pages = Page.search(domain, order=sort_order)
if sortby != 'url' or not request.session.debug:
pages = pages.filtered(pages._is_most_specific_page)
pages = pages._get_most_specific_pages()
pages_count = len(pages)
step = 50
+85
View File
@@ -2,11 +2,14 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
import re
from odoo import api, fields, models, _
from odoo.addons.website.tools import text_from_html
from odoo.http import request
from odoo.osv import expression
from odoo.exceptions import AccessError
from odoo.tools import escape_psql
from odoo.tools.json import scriptsafe as json_safe
logger = logging.getLogger(__name__)
@@ -252,3 +255,85 @@ class WebsitePublishedMultiMixin(WebsitePublishedMixin):
return (['!'] if value is False else []) + expression.AND([is_published, on_current_website])
else: # should be in the backend, return things that are published anywhere
return is_published
class WebsiteSearchableMixin(models.AbstractModel):
"""Mixin to be inherited by all models that need to searchable through website"""
_name = 'website.searchable.mixin'
_description = 'Website Searchable Mixin'
@api.model
def _search_build_domain(self, domain_list, search, fields, extra=None):
"""
Builds a search domain AND-combining a base domain with partial matches of each term in
the search expression in any of the fields.
:param domain_list: base domain list combined in the search expression
:param search: search expression string
:param fields: list of field names to match the terms of the search expression with
:param extra: function that returns an additional subdomain for a search term
:return: domain limited to the matches of the search expression
"""
domains = domain_list.copy()
if search:
for search_term in search.split(' '):
subdomains = [[(field, 'ilike', escape_psql(search_term))] for field in fields]
if extra:
subdomains.append(extra(self.env, search_term))
domains.append(expression.OR(subdomains))
return expression.AND(domains)
@api.model
def _search_get_detail(self, website, order, options):
"""
Returns indications on how to perform the searches
:param website: website within which the search is done
:param order: order in which the results are to be returned
:param options: search options
:return: search detail as expected in elements of the result of website._search_get_details()
These elements contain the following fields:
- model: name of the searched model
- base_domain: list of domains within which to perform the search
- search_fields: fields within which the search term must be found
- fetch_fields: fields from which data must be fetched
- mapping: mapping from the results towards the structure used in rendering templates.
The mapping is a dict that associates the rendering name of each field
to a dict containing the 'name' of the field in the results list and the 'type'
that must be used for rendering the value
- icon: name of the icon to use if there is no image
This method must be implemented by all models that inherit this mixin.
"""
raise NotImplementedError()
@api.model
def _search_fetch(self, search_detail, search, limit, order):
fields = search_detail['search_fields']
base_domain = search_detail['base_domain']
domain = self._search_build_domain(base_domain, search, fields, search_detail.get('search_extra'))
model = self.sudo() if search_detail.get('requires_sudo') else self
results = model.search(
domain,
limit=limit,
order=search_detail.get('order', order)
)
count = model.search_count(domain)
return results, count
def _search_render_results(self, fetch_fields, mapping, icon, limit):
results_data = self.read(fetch_fields)[:limit]
for result in results_data:
result['_fa'] = icon
result['_mapping'] = mapping
html_fields = [config['name'] for config in mapping.values() if config.get('html')]
if html_fields:
for result, data in zip(self, results_data):
for html_field in html_fields:
if data[html_field]:
text = text_from_html(data[html_field])
text = re.sub('\\s+', ' ', text).strip()
data[html_field] = text
return results_data
+3 -54
View File
@@ -1483,19 +1483,7 @@ class Website(models.Model):
:param order: order in which the results are to be returned
:param options: search options
:return list of objects with:
- model: name of the searched model
- base_domain: domain within which to perform the search
- search_fields: fields within which the search term must be found
- secondary_search_fields: optionally performs a second search
- filter_function: optionally filters obtained results
- fetch_fields: fields from which data must be fetched
- patch_data_function: optionally sets additional fields for rendering
- mapping: mapping from the results towards the structure used in rendering templates.
The mapping is a dict that associates the rendering name of each field
to a dict containing the 'name' of the field in the results list and the 'type'
that must be used for rendering the value
- icon: name of the icon to use if there is no image
:return: list of search details obtained from the `website.searchable.mixin`'s `_search_get_detail()`
"""
result = []
if search_type in ['pages', 'all']:
@@ -1554,36 +1542,11 @@ class Website(models.Model):
total_count = 0
for search_detail in search_details:
model = self.env[search_detail['model']]
fields = search_detail['search_fields']
base_domain = search_detail['base_domain']
domain = self._search_build_domain(base_domain, search, fields, search_detail.get('search_extra'))
if search_detail.get('requires_sudo'):
model = model.sudo()
results = model.search(
domain,
limit=limit,
order=search_detail.get('order', order)
)
if search:
base_results = results
secondary_fields = search_detail.get('secondary_search_fields')
if secondary_fields:
domain = self._search_build_domain(base_domain, search, secondary_fields)
results = model.search(
domain,
limit=limit,
order=search_detail.get('order', order)
)
results = results.union(base_results)
filter_function = search_detail.get('filter_function')
if filter_function:
results = results.filtered(lambda result: filter_function(search, result, base_results, results))
results, count = model._search_fetch(search_detail, search, limit, order)
search_detail['results'] = results
count = model.search_count(domain)
total_count += count
search_detail['count'] = count
all_results.append(search_detail)
return total_count, all_results
def _search_render_results(self, search_details, limit):
@@ -1599,23 +1562,9 @@ class Website(models.Model):
for search_detail in search_details:
fields = search_detail['fetch_fields']
results = search_detail['results']
results_data = results.read(fields)[:limit]
icon = search_detail['icon']
mapping = search_detail['mapping']
for result in results_data:
result['_fa'] = icon
result['_mapping'] = mapping
html_fields = [config['name'] for config in mapping.values() if config.get('html')]
patch_function = search_detail.get('patch_data_function')
if patch_function or html_fields:
for result, data in zip(results, results_data):
for html_field in html_fields:
if data[html_field]:
text = self._search_text_from_html(data[html_field])
text = re.sub('\\s+', ' ', text).strip()
data[html_field] = text
if patch_function:
patch_function(result, data)
results_data = results._search_render_results(fields, mapping, icon, limit)
search_detail['results_data'] = results_data
return search_details
+34 -31
View File
@@ -4,6 +4,7 @@
import re
from odoo.addons.http_routing.models.ir_http import slugify
from odoo.addons.website.tools import text_from_html
from odoo import api, fields, models
from odoo.tools.safe_eval import safe_eval
@@ -11,7 +12,10 @@ from odoo.tools.safe_eval import safe_eval
class Page(models.Model):
_name = 'website.page'
_inherits = {'ir.ui.view': 'view_id'}
_inherit = 'website.published.multi.mixin'
_inherit = [
'website.published.multi.mixin',
'website.searchable.mixin',
]
_description = 'Page'
_order = 'website_id'
@@ -57,14 +61,16 @@ class Page(models.Model):
not page.date_publish or page.date_publish < fields.Datetime.now()
)
def _is_most_specific_page(self, page_to_test):
'''This will test if page_to_test is the most specific page in self.'''
pages_for_url = self.sorted(key=lambda p: not p.website_id).filtered(lambda page: page.url == page_to_test.url)
# this works because pages are _order'ed by website_id
most_specific_page = pages_for_url[0]
return most_specific_page == page_to_test
def _get_most_specific_pages(self):
''' Returns the most specific pages in self. '''
ids = []
previous_page = None
# Iterate a single time on the whole list sorted on specific-website first.
for page in self.sorted(key=lambda p: (p.url, not p.website_id)):
if not previous_page or page.url != previous_page.url:
ids.append(page.id)
previous_page = page
return self.filtered(lambda page: page.id in ids)
def get_page_properties(self):
self.ensure_one()
@@ -233,15 +239,6 @@ class Page(models.Model):
@api.model
def _search_get_detail(self, website, order, options):
"""
Returns indications on how to perform the searches
:param website: website within which the search is done
:param order: order in which the results are to be returned
:param options: search options
:return search detail as expected in elements of the result of website._search_get_details()
"""
with_description = options['displayDescription']
# Read access on website.page requires sudo.
requires_sudo = True
@@ -250,36 +247,42 @@ class Page(models.Model):
# Rule must be reinforced because of sudo.
domain.append([('website_published', '=', True)])
search_fields = ['name', 'url']
fetch_fields = ['id', 'name', 'url']
mapping = {
'name': {'name': 'name', 'type': 'text', 'match': True},
'website_url': {'name': 'url', 'type': 'text'},
}
if with_description:
search_fields.append('view_id.arch_db')
fetch_fields.append('arch')
mapping['description'] = {'name': 'arch', 'type': 'text', 'html': True, 'match': True}
def filter_page(search, page, base_pages, all_pages):
if not all_pages._is_most_specific_page(page):
return False
if page in base_pages:
return True
text = '%s %s' % (page.name, page.url)
if with_description:
text = '%s %s' % (text, website._search_text_from_html(page.arch))
pattern = '|'.join([re.escape(search_term) for search_term in search.split()])
return re.findall('(%s)' % pattern, text, flags=re.I) if pattern else False
return {
'model': 'website.page',
'base_domain': domain,
'requires_sudo': requires_sudo,
'search_fields': ['name', 'url'],
'secondary_search_fields': ['name', 'url', 'view_id.arch_db'] if with_description else None,
'filter_function': filter_page,
'search_fields': search_fields,
'fetch_fields': fetch_fields,
'mapping': mapping,
'icon': 'fa-file-o',
}
@api.model
def _search_fetch(self, search_detail, search, limit, order):
with_description = 'description' in search_detail['mapping']
results, count = super()._search_fetch(search_detail, search, limit, order)
def filter_page(search, page, all_pages):
# Search might have matched words in the xml tags and parameters therefore we make
# sure the terms actually appear inside the text.
text = '%s %s %s' % (page.name, page.url, text_from_html(page.arch))
pattern = '|'.join([re.escape(search_term) for search_term in search.split()])
return re.findall('(%s)' % pattern, text, flags=re.I) if pattern else False
if 'url' not in order:
results = results._get_most_specific_pages()
if search and with_description:
results = results.filtered(lambda result: filter_page(search, result, results))
return results, count
# this is just a dummy function to be used as ormcache key
def _cached_response():
+14 -7
View File
@@ -14,7 +14,13 @@ from odoo.tools import html2plaintext
class Blog(models.Model):
_name = 'blog.blog'
_description = 'Blog'
_inherit = ['mail.thread', 'website.seo.metadata', 'website.multi.mixin', 'website.cover_properties.mixin']
_inherit = [
'mail.thread',
'website.seo.metadata',
'website.multi.mixin',
'website.cover_properties.mixin',
'website.searchable.mixin',
]
_order = 'name'
name = fields.Char('Blog Name', required=True, translate=True)
@@ -88,7 +94,6 @@ class Blog(models.Model):
@api.model
def _search_get_detail(self, website, order, options):
"""See website_page._search_get_detail()"""
with_description = options['displayDescription']
search_fields = ['name']
fetch_fields = ['id', 'name']
@@ -100,19 +105,21 @@ class Blog(models.Model):
search_fields.append('subtitle')
fetch_fields.append('subtitle')
mapping['description'] = {'name': 'subtitle', 'type': 'text', 'match': True}
def patch_blog(blog, data):
data['url'] = '/blog/%s' % data['id']
return {
'model': 'blog.blog',
'base_domain': [website.website_domain()],
'search_fields': search_fields,
'fetch_fields': fetch_fields,
'patch_data_function': patch_blog,
'mapping': mapping,
'icon': 'fa-rss-square',
'order': 'name desc, id desc' if 'name desc' in order else 'name asc, id desc',
}
def _search_render_results(self, fetch_fields, mapping, icon, limit):
results_data = super()._search_render_results(fetch_fields, mapping, icon, limit)
for data in results_data:
data['url'] = '/blog/%s' % data['id']
return results_data
class BlogTagCategory(models.Model):
_name = 'blog.tag.category'
@@ -145,7 +152,8 @@ class BlogTag(models.Model):
class BlogPost(models.Model):
_name = "blog.post"
_description = "Blog Post"
_inherit = ['mail.thread', 'website.seo.metadata', 'website.published.multi.mixin', 'website.cover_properties.mixin']
_inherit = ['mail.thread', 'website.seo.metadata', 'website.published.multi.mixin',
'website.cover_properties.mixin', 'website.searchable.mixin']
_order = 'id DESC'
_mail_post_access = 'read'
@@ -297,7 +305,6 @@ class BlogPost(models.Model):
@api.model
def _search_get_detail(self, website, order, options):
"""See website_page._search_get_detail()"""
with_description = options['displayDescription']
with_date = options['displayDetail']
blog = options.get('blog')
+12 -7
View File
@@ -23,7 +23,8 @@ class Event(models.Model):
'event.event',
'website.seo.metadata',
'website.published.multi.mixin',
'website.cover_properties.mixin'
'website.cover_properties.mixin',
'website.searchable.mixin',
]
def _default_cover_properties(self):
@@ -467,7 +468,6 @@ class Event(models.Model):
@api.model
def _search_get_detail(self, website, order, options):
"""See website_page._search_get_detail()"""
with_description = options['displayDescription']
with_date = options['displayDetail']
date = options.get('date', 'all')
@@ -527,16 +527,11 @@ class Event(models.Model):
mapping['description'] = {'name': 'subtitle', 'type': 'text', 'match': True}
if with_date:
mapping['detail'] = {'name': 'range', 'type': 'html'}
def patch_event(event, data):
begin = self.env['ir.qweb.field.date'].record_to_html(event, 'date_begin', {})
end = self.env['ir.qweb.field.date'].record_to_html(event, 'date_end', {})
data['range'] = '%s🠖%s' % (begin, end) if begin != end else begin
return {
'model': 'event.event',
'base_domain': domain,
'search_fields': search_fields,
'fetch_fields': fetch_fields,
'patch_data_function': patch_event if with_date else None,
'mapping': mapping,
'icon': 'fa-ticket',
# for website_event main controller:
@@ -546,3 +541,13 @@ class Event(models.Model):
'no_date_domain': no_date_domain,
'no_country_domain': no_country_domain,
}
def _search_render_results(self, fetch_fields, mapping, icon, limit):
with_date = 'detail' in mapping
results_data = super()._search_render_results(fetch_fields, mapping, icon, limit)
if with_date:
for event, data in zip(self, results_data):
begin = self.env['ir.qweb.field.date'].record_to_html(event, 'date_begin', {})
end = self.env['ir.qweb.field.date'].record_to_html(event, 'date_end', {})
data['range'] = '%s🠖%s' % (begin, end) if begin != end else begin
return results_data
+27 -12
View File
@@ -19,7 +19,13 @@ _logger = logging.getLogger(__name__)
class Forum(models.Model):
_name = 'forum.forum'
_description = 'Forum'
_inherit = ['mail.thread', 'image.mixin', 'website.seo.metadata', 'website.multi.mixin']
_inherit = [
'mail.thread',
'image.mixin',
'website.seo.metadata',
'website.multi.mixin',
'website.searchable.mixin',
]
_order = "sequence"
# description and use
@@ -263,7 +269,6 @@ class Forum(models.Model):
@api.model
def _search_get_detail(self, website, order, options):
"""See website_page._search_get_detail()"""
with_description = options['displayDescription']
search_fields = ['name']
fetch_fields = ['id', 'name']
@@ -275,25 +280,32 @@ class Forum(models.Model):
search_fields.append('description')
fetch_fields.append('description')
mapping['description'] = {'name': 'description', 'type': 'text', 'match': True}
def patch_forum(forum, data):
data['website_url'] = forum._compute_website_url()
return {
'model': 'forum.forum',
'base_domain': [website.website_domain()],
'search_fields': search_fields,
'fetch_fields': fetch_fields,
'patch_data_function': patch_forum,
'mapping': mapping,
'icon': 'fa-comments-o',
'order': 'name desc, id desc' if 'name desc' in order else 'name asc, id desc',
}
def _search_render_results(self, fetch_fields, mapping, icon, limit):
results_data = super()._search_render_results(fetch_fields, mapping, icon, limit)
for forum, data in zip(self, results_data):
data['website_url'] = forum._compute_website_url()
return results_data
class Post(models.Model):
_name = 'forum.post'
_description = 'Forum Post'
_inherit = ['mail.thread', 'website.seo.metadata']
_inherit = [
'mail.thread',
'website.seo.metadata',
'website.searchable.mixin',
]
_order = "is_correct DESC, vote_count DESC, write_date DESC"
name = fields.Char('Title')
@@ -963,7 +975,6 @@ class Post(models.Model):
@api.model
def _search_get_detail(self, website, order, options):
"""See website_page._search_get_detail()"""
with_description = options['displayDescription']
with_date = options['displayDetail']
search_fields = ['name']
@@ -1012,21 +1023,25 @@ class Post(models.Model):
if with_date:
fetch_fields.append('write_date')
mapping['detail'] = {'name': 'date', 'type': 'html'}
def patch_forum_post(post, data):
data['website_url'] = post._compute_website_url()
if with_date:
data['date'] = self.env['ir.qweb.field.date'].record_to_html(post, 'write_date', {})
return {
'model': 'forum.post',
'base_domain': [domain],
'search_fields': search_fields,
'fetch_fields': fetch_fields,
'patch_data_function': patch_forum_post,
'mapping': mapping,
'icon': 'fa-comment-o',
'order': order,
}
def _search_render_results(self, fetch_fields, mapping, icon, limit):
with_date = 'detail' in mapping
results_data = super()._search_render_results(fetch_fields, mapping, icon, limit)
for post, data in zip(self, results_data):
data['website_url'] = post._compute_website_url()
if with_date:
data['date'] = self.env['ir.qweb.field.date'].record_to_html(post, 'write_date', {})
return results_data
class PostReason(models.Model):
_name = "forum.post.reason"
+12 -5
View File
@@ -139,7 +139,12 @@ class ProductPricelist(models.Model):
class ProductPublicCategory(models.Model):
_name = "product.public.category"
_inherit = ["website.seo.metadata", "website.multi.mixin", 'image.mixin']
_inherit = [
'website.seo.metadata',
'website.multi.mixin',
'website.searchable.mixin',
'image.mixin',
]
_description = "Website Product Category"
_parent_store = True
_order = "sequence, name, id"
@@ -179,7 +184,6 @@ class ProductPublicCategory(models.Model):
@api.model
def _search_get_detail(self, website, order, options):
"""See website_page._search_get_detail()"""
with_description = options['displayDescription']
search_fields = ['name']
fetch_fields = ['id', 'name']
@@ -191,15 +195,18 @@ class ProductPublicCategory(models.Model):
search_fields.append('website_description')
fetch_fields.append('website_description')
mapping['description'] = {'name': 'website_description', 'type': 'text', 'match': True}
def patch_category(category, data):
data['url'] = '/shop/category/%s' % data['id']
return {
'model': 'product.public.category',
'base_domain': [], # categories are not website-specific
'search_fields': search_fields,
'fetch_fields': fetch_fields,
'patch_data_function': patch_category,
'mapping': mapping,
'icon': 'fa-folder-o',
'order': 'name desc, id desc' if 'name desc' in order else 'name asc, id desc',
}
def _search_render_results(self, fetch_fields, mapping, icon, limit):
results_data = super()._search_render_results(fetch_fields, mapping, icon, limit)
for data in results_data:
data['url'] = '/shop/category/%s' % data['id']
return results_data
+26 -15
View File
@@ -8,7 +8,13 @@ from odoo.osv import expression
class ProductTemplate(models.Model):
_inherit = ["product.template", "website.seo.metadata", 'website.published.multi.mixin', 'rating.mixin']
_inherit = [
"product.template",
"website.seo.metadata",
'website.published.multi.mixin',
'website.searchable.mixin',
'rating.mixin',
]
_name = 'product.template'
_mail_post_access = 'read'
_check_company_auto = True
@@ -323,7 +329,6 @@ class ProductTemplate(models.Model):
@api.model
def _search_get_detail(self, website, order, options):
"""See website_page._search_get_detail()"""
with_image = options['displayImage']
with_description = options['displayDescription']
with_category = options['displayExtraLink']
@@ -367,15 +372,29 @@ class ProductTemplate(models.Model):
fetch_fields.append('description_sale')
mapping['description'] = {'name': 'description_sale', 'type': 'text', 'match': True}
if with_price:
mapping['detail'] = {'name': 'price', 'type': 'html'}
mapping['detail_strike'] = {'name': 'list_price', 'type': 'html'}
mapping['detail'] = {'name': 'price', 'type': 'html', 'display_currency': options['display_currency']}
mapping['detail_strike'] = {'name': 'list_price', 'type': 'html', 'display_currency': options['display_currency']}
if with_category:
mapping['extra_link'] = {'name': 'category', 'type': 'text', 'match': True}
mapping['extra_link_url'] = {'name': 'category_url', 'type': 'text'}
def patch_product(product, data):
return {
'model': 'product.template',
'base_domain': domains,
'search_fields': search_fields,
'fetch_fields': fetch_fields,
'mapping': mapping,
'icon': 'fa-shopping-cart',
}
def _search_render_results(self, fetch_fields, mapping, icon, limit):
with_image = 'image_url' in mapping
with_category = 'extra_link' in mapping
with_price = 'detail' in mapping
results_data = super()._search_render_results(fetch_fields, mapping, icon, limit)
for product, data in zip(self, results_data):
if with_price:
combination_info = product._get_combination_info(only_template=True)
monetary_options = {'display_currency': options['display_currency']}
monetary_options = {'display_currency': mapping['detail']['display_currency']}
data['price'] = self.env['ir.qweb.field.monetary'].value_to_html(combination_info['price'], monetary_options)
if combination_info['has_discounted_price']:
data['list_price'] = self.env['ir.qweb.field.monetary'].value_to_html(combination_info['list_price'], monetary_options)
@@ -385,12 +404,4 @@ class ProductTemplate(models.Model):
data['category'] = _('Category: %s', product.public_categ_ids.name)
slugs = [slug(category) for category in product.public_categ_ids]
data['category_url'] = '/shop/category/%s' % ','.join(slugs)
return {
'model': 'product.template',
'base_domain': domains,
'search_fields': search_fields,
'fetch_fields': fetch_fields,
'patch_data_function': patch_product,
'mapping': mapping,
'icon': 'fa-shopping-cart',
}
return results_data
@@ -137,7 +137,10 @@ class Channel(models.Model):
'mail.thread', 'rating.mixin',
'mail.activity.mixin',
'image.mixin',
'website.seo.metadata', 'website.published.multi.mixin']
'website.seo.metadata',
'website.published.multi.mixin',
'website.searchable.mixin',
]
_order = 'sequence, id'
def _default_access_token(self):
@@ -834,7 +837,6 @@ class Channel(models.Model):
@api.model
def _search_get_detail(self, website, order, options):
"""See website_page._search_get_detail()"""
with_description = options['displayDescription']
with_date = options['displayDetail']
my = options.get('my')
+18 -13
View File
@@ -116,7 +116,10 @@ class Slide(models.Model):
_inherit = [
'mail.thread',
'image.mixin',
'website.seo.metadata', 'website.published.mixin']
'website.seo.metadata',
'website.published.mixin',
'website.searchable.mixin',
]
_description = 'Slides'
_mail_post_access = 'read'
_order_by_strategy = {
@@ -890,7 +893,6 @@ class Slide(models.Model):
@api.model
def _search_get_detail(self, website, order, options):
"""See website_page._search_get_detail()"""
with_description = options['displayDescription']
search_fields = ['name']
fetch_fields = ['id', 'name']
@@ -904,6 +906,17 @@ class Slide(models.Model):
search_fields.append('description')
fetch_fields.append('description')
mapping['description'] = {'name': 'description', 'type': 'text', 'html': True, 'match': True}
return {
'model': 'slide.slide',
'base_domain': [website.website_domain()],
'search_fields': search_fields,
'fetch_fields': fetch_fields,
'mapping': mapping,
'icon': 'fa-shopping-cart',
'order': 'name desc, id desc' if 'name desc' in order else 'name asc, id desc',
}
def _search_render_results(self, fetch_fields, mapping, icon, limit):
icon_per_type = {
'infographic': 'fa-file-picture-o',
'webpage': 'fa-file-text',
@@ -913,18 +926,10 @@ class Slide(models.Model):
'quiz': 'fa-question-circle',
'link': 'fa-file-code-o', # appears in template "slide_icon"
}
def patch_slide(slide, data):
results_data = super()._search_render_results(fetch_fields, mapping, icon, limit)
for slide, data in zip(self, results_data):
data['_fa'] = icon_per_type.get(slide.slide_type, 'fa-file-pdf-o')
data['url'] = slide.website_url
data['course'] = _('Course: %s', slide.channel_id.name)
data['course_url'] = slide.channel_id.website_url
return {
'model': 'slide.slide',
'base_domain': [website.website_domain()],
'search_fields': search_fields,
'fetch_fields': fetch_fields,
'patch_data_function': patch_slide,
'mapping': mapping,
'icon': 'fa-shopping-cart',
'order': 'name desc, id desc' if 'name desc' in order else 'name asc, id desc',
}
return results_data