server-tools/base_name_search_improved/models/ir_model.py

77 lines
3.1 KiB
Python

# Copyright 2016 Daniel Reis
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models, tools
# Extended name search is only used on some operators
ALLOWED_OPS = {"ilike", "like"}
@tools.ormcache(skiparg=0)
def _get_rec_names(self):
"List of fields to search into"
model = self.env["ir.model"].search([("model", "=", self._name)])
rec_name = [self._rec_name] if bool(self._rec_name) else []
other_names = model.name_search_ids.mapped("name")
return rec_name + other_names
def _extend_name_results(self, domain, results, limit):
result_count = len(results)
if result_count < limit:
domain += [("id", "not in", [x[0] for x in results])]
recs = self.search(domain, limit=limit - result_count)
results.extend(recs.name_get())
return results
class IrModel(models.Model):
_inherit = "ir.model"
name_search_ids = fields.Many2many("ir.model.fields", string="Name Search Fields")
@api.model_cr
def _register_hook(self):
def make_name_search():
@api.model
def name_search(self, name="", args=None, operator="ilike", limit=100):
# Perform standard name search
res = name_search.origin(
self, name=name, args=args, operator=operator, limit=limit
)
enabled = self.env.context.get("name_search_extended", True)
# Perform extended name search
# Note: Empty name causes error on
# Customer->More->Portal Access Management
if name and enabled and operator in ALLOWED_OPS:
# Support a list of fields to search on
all_names = _get_rec_names(self)
base_domain = args or []
# Try regular search on each additional search field
for rec_name in all_names[1:]:
domain = [(rec_name, operator, name)]
res = _extend_name_results(
self, base_domain + domain, res, limit
)
# Try ordered word search on each of the search fields
for rec_name in all_names:
domain = [(rec_name, operator, name.replace(" ", "%"))]
res = _extend_name_results(
self, base_domain + domain, res, limit
)
# Try unordered word search on each of the search fields
for rec_name in all_names:
domain = [(rec_name, operator, x) for x in name.split() if x]
res = _extend_name_results(
self, base_domain + domain, res, limit
)
return res
return name_search
for model in self.sudo().search(self.ids or []):
Model = self.env.get(model.model)
if Model is not None:
Model._patch_method("name_search", make_name_search())
return super(IrModel, self)._register_hook()