[IMP] base_name_search_improved: black, isort, prettier
parent
58f6aaa2df
commit
21daec5241
|
@ -1,18 +1,14 @@
|
|||
# Copyright 2016 Daniel Reis
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
{
|
||||
'name': 'Improved Name Search',
|
||||
'summary': 'Friendlier search when typing in relation fields',
|
||||
'version': '11.0.1.0.0',
|
||||
'category': 'Uncategorized',
|
||||
'website': 'https://github.com/OCA/server-tools',
|
||||
'author': 'Daniel Reis, Odoo Community Association (OCA)',
|
||||
'license': 'AGPL-3',
|
||||
'data': [
|
||||
'views/ir_model_views.xml',
|
||||
],
|
||||
'depends': [
|
||||
'base',
|
||||
],
|
||||
'installable': True,
|
||||
"name": "Improved Name Search",
|
||||
"summary": "Friendlier search when typing in relation fields",
|
||||
"version": "11.0.1.0.0",
|
||||
"category": "Uncategorized",
|
||||
"website": "https://github.com/OCA/server-tools",
|
||||
"author": "Daniel Reis, Odoo Community Association (OCA)",
|
||||
"license": "AGPL-3",
|
||||
"data": ["views/ir_model_views.xml",],
|
||||
"depends": ["base",],
|
||||
"installable": True,
|
||||
}
|
||||
|
|
|
@ -1,51 +1,45 @@
|
|||
# Copyright 2016 Daniel Reis
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, fields, api, tools
|
||||
from odoo import api, fields, models, tools
|
||||
|
||||
# Extended name search is only used on some operators
|
||||
ALLOWED_OPS = {'ilike', 'like'}
|
||||
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)])
|
||||
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')
|
||||
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])]
|
||||
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'
|
||||
_inherit = "ir.model"
|
||||
|
||||
name_search_ids = fields.Many2many(
|
||||
'ir.model.fields',
|
||||
string='Name Search Fields')
|
||||
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):
|
||||
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)
|
||||
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
|
||||
|
@ -57,24 +51,26 @@ class IrModel(models.Model):
|
|||
for rec_name in all_names[1:]:
|
||||
domain = [(rec_name, operator, name)]
|
||||
res = _extend_name_results(
|
||||
self, base_domain + domain, res, limit)
|
||||
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(' ', '%'))]
|
||||
domain = [(rec_name, operator, name.replace(" ", "%"))]
|
||||
res = _extend_name_results(
|
||||
self, base_domain + domain, res, limit)
|
||||
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]
|
||||
domain = [(rec_name, operator, x) for x in name.split() if x]
|
||||
res = _extend_name_results(
|
||||
self, base_domain + domain, res, limit)
|
||||
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())
|
||||
Model._patch_method("name_search", make_name_search())
|
||||
return super(IrModel, self)._register_hook()
|
||||
|
|
|
@ -7,47 +7,49 @@ from odoo.tests.common import TransactionCase, at_install, post_install
|
|||
@at_install(False)
|
||||
@post_install(True)
|
||||
class NameSearchCase(TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(NameSearchCase, self).setUp()
|
||||
phone_field = self.env.ref('base.field_res_partner_phone')
|
||||
model_partner = self.env.ref('base.model_res_partner')
|
||||
phone_field = self.env.ref("base.field_res_partner_phone")
|
||||
model_partner = self.env.ref("base.model_res_partner")
|
||||
model_partner.name_search_ids = phone_field
|
||||
self.Partner = self.env['res.partner']
|
||||
self.Partner = self.env["res.partner"]
|
||||
self.partner1 = self.Partner.create(
|
||||
{'name': 'Luigi Verconti',
|
||||
'customer': True,
|
||||
'phone': '+351 555 777 333'})
|
||||
{"name": "Luigi Verconti", "customer": True, "phone": "+351 555 777 333"}
|
||||
)
|
||||
self.partner2 = self.Partner.create(
|
||||
{'name': 'Ken Shabby',
|
||||
'customer': True,
|
||||
'phone': '+351 555 333 777'})
|
||||
{"name": "Ken Shabby", "customer": True, "phone": "+351 555 333 777"}
|
||||
)
|
||||
self.partner3 = self.Partner.create(
|
||||
{'name': 'Johann Gambolputty of Ulm',
|
||||
'supplier': True,
|
||||
'phone': '+351 777 333 555'})
|
||||
{
|
||||
"name": "Johann Gambolputty of Ulm",
|
||||
"supplier": True,
|
||||
"phone": "+351 777 333 555",
|
||||
}
|
||||
)
|
||||
|
||||
def test_RelevanceOrderedResults(self):
|
||||
"""Return results ordered by relevance"""
|
||||
res = self.Partner.name_search('555 777')
|
||||
res = self.Partner.name_search("555 777")
|
||||
self.assertEqual(
|
||||
res[0][0], self.partner1.id,
|
||||
'Match full string honoring spaces')
|
||||
res[0][0], self.partner1.id, "Match full string honoring spaces"
|
||||
)
|
||||
self.assertEqual(
|
||||
res[1][0], self.partner2.id,
|
||||
'Match words honoring order of appearance')
|
||||
res[1][0], self.partner2.id, "Match words honoring order of appearance"
|
||||
)
|
||||
self.assertEqual(
|
||||
res[2][0], self.partner3.id,
|
||||
'Match all words, regardless of order of appearance')
|
||||
res[2][0],
|
||||
self.partner3.id,
|
||||
"Match all words, regardless of order of appearance",
|
||||
)
|
||||
|
||||
def test_NameSearchMustMatchAllWords(self):
|
||||
"""Must Match All Words"""
|
||||
res = self.Partner.name_search('ulm 555 777')
|
||||
res = self.Partner.name_search("ulm 555 777")
|
||||
self.assertFalse(res)
|
||||
|
||||
def test_MustHonorDomain(self):
|
||||
"""Must also honor a provided Domain"""
|
||||
res = self.Partner.name_search('+351', args=[('supplier', '=', True)])
|
||||
res = self.Partner.name_search("+351", args=[("supplier", "=", True)])
|
||||
gambulputty = self.partner3.id
|
||||
self.assertEqual(len(res), 1)
|
||||
self.assertEqual(res[0][0], gambulputty)
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!-- Copyright 2016 Daniel Reis
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="view_model_form" model="ir.ui.view">
|
||||
<field name="name">Add Name Searchable to Models</field>
|
||||
<field name="model">ir.model</field>
|
||||
<field name="inherit_id" ref="base.view_model_form"/>
|
||||
<field name="inherit_id" ref="base.view_model_form" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="state" position="after">
|
||||
<field name="name_search_ids"
|
||||
widget="many2many_tags"
|
||||
domain="[('model_id', '=', id)]"
|
||||
/>
|
||||
<field
|
||||
name="name_search_ids"
|
||||
widget="many2many_tags"
|
||||
domain="[('model_id', '=', id)]"
|
||||
/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
Loading…
Reference in New Issue