Odoo-добавить атрибут настраиваемого поля?

есть ли способ добавить пользовательский атрибут поля в Odoo? Например каждое поле имеет атрибут help где вы можете ввести сообщение, в поле для пользователя. Поэтому я хочу добавить пользовательский атрибут, чтобы изменить способ действия поля для всех типов полей.

Я хочу добавить в Field class, поэтому все поля получат этот атрибут. Но, похоже, что бы я ни делал, оду не видит, что такой атрибут был добавлен.

если я просто добавлю новый пользовательский атрибут типа:

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

тогда это просто игнорируется. И мне нужно, чтобы он был подобран методом fields_get, который может возвращать значение атрибута wanted (информация о том, что он делает:

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 ответов


предполагая v9

результат fields_get - это сводка полей, определенных на модели,код показывает, что он добавит атрибут только в том случае, если описание было заполнено. Он будет получать описание текущего поля по телефону 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

это только то, что вы можете сделать, если вы запустите 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