Odoo - 为附件实施标签系统
Odoo - Implementing a tag system for attachments
有人要求我为 Odoo 中的附件开发一个标签系统。
虽然我找到了 this standard module(称为文档管理系统)附件,但我没有找到任何对标签管理有用的东西。
因此,我开发了自己的自定义模块,其中附件(由核心 ir.attachment
模型表示)已通过与 tag
模型的 Many2many 关系进行了扩展,反过来代表...一个标签,并且有一个 tag
字段代表实际标签的文本内容。
然后我一直在努力按标签搜索...
Odoo 搜索视图基于 A OP B
表达式,其中 A
是模型字段,OP
是运算符(例如 =
),B
(通常)是搜索词(但它可以是任何 Python 表达式)。
这里的问题是搜索词必须与相关对象的字段(即标签)进行比较,不与附件本身的字段。
所以我想出了一个解决方法。我扩展了附件模型:
- 一个名为
tags
的 computed 字符字段,具有关联的自定义搜索方法 _search_tags
- 一个名为
found_by_tag
的布尔字段
每次执行搜索时都会调用 _search_tags
,其工作是根据搜索的词将标志 found_by_tag
设置为正确的值。
因此,搜索视图的表达式变为 [('found_by_tag', '=', True)]
。
这是 Python 代码的相关部分:
# Attachments
class attachment(models.Model):
_inherit = 'ir.attachment'
# Tag management
tag_ids = fields.Many2many('attachmentssample.tag', string = 'Tags')
tags = fields.Text(compute = '_compute_tags', search = '_search_tags')
found_by_tag = fields.Boolean()
@api.one
@api.depends('tag_ids')
def _compute_tags(self):
tags = ''
for tag in self.tag_ids:
tags += tag.tag + ','
self.tags = tags
def _search_tags(self, operator, value):
attachments = self.search([])
for attachment in attachments:
attachment.checkIfRelevantFor(value)
return [('found_by_tag', '=', True)]
def checkIfRelevantFor(self, search_tag):
relevant = False
for tag in self.tag_ids:
if tag.tag == search_tag:
relevant = True
if relevant:
self.found_by_tag = True
else:
self.found_by_tag = False
# Tags
class tag(models.Model):
_name = 'attachmentssample.tag'
tag = fields.Char()
虽然解决方法确实有效,但我想知道这是否太多了。有没有更简单的方法来实现按标签搜索?或者,是否有可用于此目的的模块?
不确定社区中是否存在此模块,
但理想情况下,从 odoo 实施指南来看,您所做的是完全正确的。如果您认为要提高 css 样式和可重用性因素,则需要为标签使用额外的模型。你会在 v9 中看到这些东西已经完成
再三考虑,如果您认为这些标签只是提供信息,那么您可以制作文本字段并存储以逗号分隔的值,并且您的辅助方法可以轻松地用逗号拆分或连接。为什么会有这个想法。因为这将大大减少每次阅读附件时标签的数据库 IO 以及 ir.attachment 链接到所有模型记录的事实,总的来说,消除 table 对性能有好处,因为 python 代码是比 db IO 快得多。
最好成绩
我想出了可能的最佳解决方案。在 Odoo Development Essentials 一书中解释说,当 left-hand 端是 "to-many" 字段时,域表达式中的 'in'
运算符的行为不同。在这种情况下,('A', 'in', B)
的语义变为 "keep the record with id B if B is one of the ids of the records referenced by A"。换句话说,表达式应该反过来读。有了这些知识,您可以分两步实现标签搜索:
- 查找与当前查询匹配的标签。
- 在像
('attachment_ids', 'in', id)
. 这样的域表达式中使用它的 id
使用此策略,您不需要额外的字段来支持搜索。
(伙计……Odoo 开发是……具有挑战性的)
有人要求我为 Odoo 中的附件开发一个标签系统。
虽然我找到了 this standard module(称为文档管理系统)附件,但我没有找到任何对标签管理有用的东西。
因此,我开发了自己的自定义模块,其中附件(由核心 ir.attachment
模型表示)已通过与 tag
模型的 Many2many 关系进行了扩展,反过来代表...一个标签,并且有一个 tag
字段代表实际标签的文本内容。
然后我一直在努力按标签搜索...
Odoo 搜索视图基于 A OP B
表达式,其中 A
是模型字段,OP
是运算符(例如 =
),B
(通常)是搜索词(但它可以是任何 Python 表达式)。
这里的问题是搜索词必须与相关对象的字段(即标签)进行比较,不与附件本身的字段。
所以我想出了一个解决方法。我扩展了附件模型:
- 一个名为
tags
的 computed 字符字段,具有关联的自定义搜索方法_search_tags
- 一个名为
found_by_tag
的布尔字段
_search_tags
,其工作是根据搜索的词将标志 found_by_tag
设置为正确的值。
因此,搜索视图的表达式变为 [('found_by_tag', '=', True)]
。
这是 Python 代码的相关部分:
# Attachments
class attachment(models.Model):
_inherit = 'ir.attachment'
# Tag management
tag_ids = fields.Many2many('attachmentssample.tag', string = 'Tags')
tags = fields.Text(compute = '_compute_tags', search = '_search_tags')
found_by_tag = fields.Boolean()
@api.one
@api.depends('tag_ids')
def _compute_tags(self):
tags = ''
for tag in self.tag_ids:
tags += tag.tag + ','
self.tags = tags
def _search_tags(self, operator, value):
attachments = self.search([])
for attachment in attachments:
attachment.checkIfRelevantFor(value)
return [('found_by_tag', '=', True)]
def checkIfRelevantFor(self, search_tag):
relevant = False
for tag in self.tag_ids:
if tag.tag == search_tag:
relevant = True
if relevant:
self.found_by_tag = True
else:
self.found_by_tag = False
# Tags
class tag(models.Model):
_name = 'attachmentssample.tag'
tag = fields.Char()
虽然解决方法确实有效,但我想知道这是否太多了。有没有更简单的方法来实现按标签搜索?或者,是否有可用于此目的的模块?
不确定社区中是否存在此模块,
但理想情况下,从 odoo 实施指南来看,您所做的是完全正确的。如果您认为要提高 css 样式和可重用性因素,则需要为标签使用额外的模型。你会在 v9 中看到这些东西已经完成
再三考虑,如果您认为这些标签只是提供信息,那么您可以制作文本字段并存储以逗号分隔的值,并且您的辅助方法可以轻松地用逗号拆分或连接。为什么会有这个想法。因为这将大大减少每次阅读附件时标签的数据库 IO 以及 ir.attachment 链接到所有模型记录的事实,总的来说,消除 table 对性能有好处,因为 python 代码是比 db IO 快得多。
最好成绩
我想出了可能的最佳解决方案。在 Odoo Development Essentials 一书中解释说,当 left-hand 端是 "to-many" 字段时,域表达式中的 'in'
运算符的行为不同。在这种情况下,('A', 'in', B)
的语义变为 "keep the record with id B if B is one of the ids of the records referenced by A"。换句话说,表达式应该反过来读。有了这些知识,您可以分两步实现标签搜索:
- 查找与当前查询匹配的标签。
- 在像
('attachment_ids', 'in', id)
. 这样的域表达式中使用它的 id
使用此策略,您不需要额外的字段来支持搜索。
(伙计……Odoo 开发是……具有挑战性的)