Odoo - 添加自定义字段属性?

时间:2016-06-10 07:35:44

标签: python attributes field openerp odoo-8

有没有办法在Odoo中添加自定义字段属性?例如,每个字段都有属性help,您可以在其中输入解释用户字段的消息。所以我想添加自定义属性,这样就会改变字段对所有类型字段的行为方式。

我想添加到Field类中,因此所有字段都会获得该属性。但似乎无论我做什么,Odoo都没有看到这样的属性被添加。

如果我只是添加新的自定义属性,如:

some_field = fields.Char(custom_att="hello")

然后它被忽略了。而且我需要通过方法fields_get来获取它,它可以返回想要的属性值(信息它的作用:

def fields_get(self, cr, user, allfields=None, context=None, write_access=True, attributes=None):
    """ fields_get([fields][, attributes])

    Return the definition of each field.

    The returned value is a dictionary (indiced by field name) of
    dictionaries. The _inherits'd fields are included. The string, help,
    and selection (if present) attributes are translated.

    :param allfields: list of fields to document, all if empty or not provided
    :param attributes: list of description attributes to return for each field, all if empty or not provided
    """

所以调用它,不会返回我的自定义属性(它会返回最初由Odoo定义的属性)。

我还尝试在_slots类中更新Field(使用猴子补丁或仅通过更改源代码进行测试)属性,但似乎还不够。因为我的属性仍然被忽略。

from openerp import fields

original_slots = fields.Field._slots

_slots = original_slots
_slots['custom_att'] = None

fields.Field._slots = _slots

有谁知道如何为字段正确添加新的自定义属性?

2 个答案:

答案 0 :(得分:3)

假设v9

fields_get的结果是模型上定义的字段的摘要,the code表示只有在填写说明时才会添加属性。它将获取当前字段by calling field.get_description

的描述

因此,为了确保您的属性已插入此self.description_attrs,您需要添加以_description_customatt开头的属性或方法(customatt部分来自您的示例)返回所需的数据。

我没有为此运行任何测试,但您可以查看字段的代码及其实际返回的属性。例如帮助属性说明(src

def _description_help(self, env):
  if self.help and env.lang:
    model_name = self.base_field.model_name
    field_help = env['ir.translation'].get_field_help(model_name)
    return field_help.get(self.name) or self.help
  return self.help

答案 1 :(得分:0)

如果您在自己的服务器上运行OpenERP / ODOO(换句话说,不是您无法访问其代码的云版本),这是您可以执行的操作。

您需要修改<base>/osv/fields.py文件,并将更改添加到文件底部的field_to_dict函数中(基础_column类已经为您保存了额外的关键字参数 - - 至少在7.0版本中):

def field_to_dict(model, cr, user, field, context=None): 
    res = {'type': field._type}
    ...
    ...
    for arg in ('string', 'readonly', ...) :

在那长长的属性列表中,您需要插入您感兴趣的名称。

或者,您可以更新_column.__init__以保存额外参数的名称,并field_to_dict包含它们(未经测试):

diff -r a30d30db3cd9 osv/fields.py
--- a/osv/fields.py Thu Jun 09 17:18:29 2016 -0700
+++ b/osv/fields.py Mon Jun 13 18:11:26 2016 -0700
@@ -116,23 +116,24 @@ class _column(object):
         self._context = context
         self.write = False
         self.read = False
         self.view_load = 0
         self.select = select
         self.manual = manual
         self.selectable = True
         self.group_operator = args.get('group_operator', False)
         self.groups = False  # CSV list of ext IDs of groups that can access this field
         self.deprecated = False # Optional deprecation warning
-        for a in args:
-            if args[a]:
-                setattr(self, a, args[a])
+        self._user_args = ()
+        for name, value in args:
+            setattr(self, name, value or False)
+            self._user_args += name

     def restart(self):
         pass

     def set(self, cr, obj, id, name, value, user=None, context=None):
         cr.execute('update '+obj._table+' set '+name+'='+self._symbol_set[0]+' where id=%s', (self._symbol_set[1](value), id))

     def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
         raise Exception(_('undefined get method !'))

@@ -1559,20 +1560,22 @@ def field_to_dict(model, cr, user, field
         res['o2m_order'] = field._order or False
     if isinstance(field, many2many):
         (table, col1, col2) = field._sql_names(model)
         res['m2m_join_columns'] = [col1, col2]
         res['m2m_join_table'] = table
     for arg in ('string', 'readonly', 'states', 'size', 'group_operator', 'required',
             'change_default', 'translate', 'help', 'select', 'selectable', 'groups',
             'deprecated', 'digits', 'invisible', 'filters'):
         if getattr(field, arg, None):
             res[arg] = getattr(field, arg)
+    for arg in field._user_args:
+        res[arg] = getattr(field, arg)

     if hasattr(field, 'selection'):
         if isinstance(field.selection, (tuple, list)):
             res['selection'] = field.selection
         else:
             # call the 'dynamic selection' function
             res['selection'] = field.selection(model, cr, user, context)
     if res['type'] in ('one2many', 'many2many', 'many2one'):
         res['relation'] = field._obj
         res['domain'] = field._domain(model) if callable(field._domain) else field._domain