如何将状态添加到选择字段并在 Odoo 11 的状态栏中显示它的顺序?

How to add a state to a Selection field and show it ordered in the statusbar in Odoo 11?

我使用参数 selection_add:

Selection 字段添加了一个新状态
state = fields.Selection(
    selection_add=[
        ('draft_ok', 'Validated Quotation'),
    ],
)

现在我想在 XML 视图中显示它,目前 state 是这样显示的:

<field name="state" widget="statusbar" statusbar_visible="draft,sent,sale"/>

如果我从该视图继承,要添加新状态:

<xpath expr="//header/field[@name='state']" position="attributes">
    <attribute name="statusbar_visible">draft,draft_ok,sent,sale</attribute>
</xpath>

新状态显示在状态栏的末尾。我想在 draftsent 状态之间显示它。

我知道的唯一方法是重新定义 Python 中的状态:

state = fields.Selection(
    selection=[
        ('draft', 'Quotation'),
        ('draft_ok', 'Validated Quotation'),
        ('sent', 'Quotation Sent'),
        ('sale', 'Sales Order'),
        ('done', 'Locked'),
        ('cancel', 'Cancelled'),
    ],
)

但是这个解决方案不是很一致,因为如果其他模块也向这个字段添加状态并且我的模块代码在它之后执行,我会销毁其他模块添加的状态。

所以我正在寻找其他方式来显示带有自定义顺序的状态栏。有什么想法吗?

来自 位于 fields.Selection class 的负责代码 没有办法做到 不使用特殊技巧:

# frame code
def _setup_attrs(self, model, name):
    super(Selection, self)._setup_attrs(model, name)
    # determine selection (applying 'selection_add' extensions)
    for field in reversed(resolve_mro(model, name, self._can_setup_from)):
        # We cannot use field.selection or field.selection_add here
        # because those attributes are overridden by ``_setup_attrs``.
        if 'selection' in field.args:
            self.selection = field.args['selection']
        if 'selection_add' in field.args:
            # use an OrderedDict to update existing values
            selection_add = field.args['selection_add']
            self.selection = OrderedDict(self.selection + selection_add).items()

例如 monkey patching 我试过正常 inheritance 它没有用我认为它需要很多工作。

这是我尝试过的,它在 Odoo 9 中运行良好。 我创建了一个新密钥 selection_add_afterdictionary

    1. key is the value of selection that you want to add item after it

    2. value is the list of selection items that you want to add
    def _setup_attrs(self, model, name):
        super(fields.Selection, self)._setup_attrs(model, name)
        # determine selection (applying 'selection_add' extensions)
        for field in reversed(fields.resolve_mro(model, name, self._can_setup_from)):
            # We cannot use field.selection or field.selection_add here
            # because those attributes are overridden by ``_setup_attrs``.
            if 'selection' in field.args:
                self.selection = field.args['selection']
            if 'selection_add' in field.args:
                # use an OrderedDict to update existing values
                selection_add = field.args['selection_add']
                self.selection = OrderedDict(self.selection + selection_add).items()
            if 'selection_add_after' in field.args:
                selection_add_atfer = field.args['selection_add_after']
                new_selection = []
                for item in self.selection:
                    new_selection.append(item) # add the element firs
                    items_to_add = selection_add_atfer.get(item[0], [])
                    for item_to_add in items_to_add:  # then add the element if there is
                        new_selection.append(item_to_add)
                # I don't know why they used OrderdedDict ???!! do you have any idea why?!!
                self.selection = OrderedDict(new_selection).items()

    # mucky patch the method in selection field
    fields.Selection._setup_attrs = _setup_attrs

确保在定义字段之前打补丁

    # add element after draft 
    state = fields.Selection(selection_add_after={'draft': [('hello', 'Hello')]})

    # add element after draft and other emelent after confirmed 
    state = fields.Selection(selection_add_after={'draft': [('hello', 'Hello')], 'confirmed': [('test','Test')]})

您可以添加新密钥,如删除或任何您想要的。

但是猴子修补框架方法也是一个坏主意,因为如果 _setup_attrs 中有任何 updates 总是 已删除

编辑

对于Odoo 11,这是代码:

def _setup_attrs(self, model, name):
    super(fields.Selection, self)._setup_attrs(model, name)
    # determine selection (applying 'selection_add' extensions)
    for field in reversed(fields.resolve_mro(model, name, self._can_setup_from)):
        # We cannot use field.selection or field.selection_add here
        # because those attributes are overridden by ``_setup_attrs``.
        if 'selection' in field.args:
            self.selection = field.args['selection']
        if 'selection_add' in field.args:
            # use an OrderedDict to update existing values
            selection_add = field.args['selection_add']
            self.selection = list(OrderedDict(self.selection + selection_add).items())
        if 'selection_add_after' in field.args:
            selection_add_atfer = field.args['selection_add_after']
            new_selection = []
            for item in self.selection:
                new_selection.append(item) # add the element firs
                items_to_add = selection_add_atfer.get(item[0], [])
                for item_to_add in items_to_add:  # then add the element if there is
                    new_selection.append(item_to_add)
            # I don't know why they used OrderdedDict ???!! do you have any idea why?!!
            self.selection = list(OrderedDict(new_selection).items())

fields.Selection._setup_attrs = _setup_attrs

试试这个方法:

state = fields.Selection(
    selection_add=[
         ('draft_ok', 'Validated Quotation'),(sent,)
    ],
)