【问题标题】:Odoo: JSON: Inherit view, hide edit button conditionallyOdoo:JSON:继承视图,有条件地隐藏编辑按钮
【发布时间】:2015-09-23 08:28:17
【问题描述】:

我正在尝试隐藏 Odoo 中物料清单表单中的编辑按钮,具体取决于布尔值的状态。

我设法使用以下代码永久删除了编辑按钮:

<xpath expr="//form[@string='Bill of Material']" position="attributes">
    <attribute name="edit">false</attribute>
</xpath>

现在我尝试使用这样的布尔值使其成为条件:

<xpath expr="//form[@string='Bill of Material']" position="attributes">
    <attribute name="edit">true:realman==True;false:realman==False;</attribute>
</xpath>

这给出了错误:

SyntaxError: JSON.parse: 意外的非空白字符后 JSON 数据第 1 行第 5 列的 JSON 数据

当我查看 javascript 文件时,我发现这是处理编辑属性的代码:

/**
 * Return whether the user can perform the action ('create', 'edit', 'delete') in this view.
 * An action is disabled by setting the corresponding attribute in the view's main element,
 * like: <form string="" create="false" edit="false" delete="false">
 */
is_action_enabled: function(action) {
    var attrs = this.fields_view.arch.attrs;
    return (action in attrs) ? JSON.parse(attrs[action]) : true;
},

当我的表单中的布尔值realmanFalse 时,我想我需要在var attrs 中获得false

我已经尝试将它写在大括号中,就像这个问题的答案一样:JSON.parse unexpected character error

这也给了我错误。

为什么会出现此错误,我该如何解决?这只是语法错误还是有更多问题?

【问题讨论】:

    标签: javascript json xml xpath openerp


    【解决方案1】:

    我通过使用 field_view_get 成功解决了类似的问题,但前提是“realman”被传递到上下文中

    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
        res = models.Model.fields_view_get(self, cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
        realman = context.get('realman', True)
        if not realman and view_type == 'form':
            doc = etree.XML(res['arch'])
            for t in doc.xpath("//form[@string='Bill of Material']"):
                t.attrib['edit'] = 'false'
            res['arch'] = etree.tostring(doc)
        return res
    

    如果 realman 是一个字段并且您需要启用/禁用编辑按钮,那么恐怕这是不可能的。哈哈。

    【讨论】:

    • 记得从lxml导入etree!
    【解决方案2】:

    正如Alessandro Ruffolo 所说,他的解决方案不适用于按钮/操作,具体取决于模型的字段。我为此用 Javascript 编写了解决方案。它适用于 ODOO 10(也应该适用于 9,但我还没有测试过)。

    示例是检查模型的“状态”字段。如果它的值为“noEditable”,则编辑和删除按钮将隐藏。覆盖 is_action_enabled 是不够的,因为 ODOO 在还没有加载数据记录时调用该方法。因此需要在do_show和reload方法后再次检查。

    // modify default form view for custom model my.custom.model
    odoo.define('my.custom_model_form', function (require) {
        "use strict";
    
        var FormView = require('web.FormView');
    
        FormView.include({
            is_action_enabled: function(action) {
                if (this.model == "my.custom.model" && this.datarecord && this.datarecord.state == "noEditable" &&
                    (action == 'delete' || action == 'edit')) {
                    // don't allow edit nor delete
                    return false;
                }
                // call default is_action_enabled method
                return this._super.apply(this, arguments);
            },
            deleteItem: null,
            deleteItemIdx: null,
            deleteItemShown: true,
            reinit_actions: function() {
                // apply for my custom model only
                if (this.model == "my.custom.model") {
                    // hide/show edit button
                    if (this.is_action_enabled('edit')) {
                        this.$buttons.find(".o_form_button_edit").show();
                    } else {
                        this.$buttons.find(".o_form_button_edit").hide();
                    }
    
                    // find delete item in sidebar's items
                    if (!this.deleteItem) {
                        // form view is adding it to "other"
                        if (this.sidebar && this.sidebar.items && this.sidebar.items.other) {
                            for (var i = 0; i < this.sidebar.items.other.length; i++) {
                                // on_button_delete is used as callback for delete button
                                // it's ugly way to find out which one is delete button, haven't found better way
                                if (this.sidebar.items.other[i].callback == this.on_button_delete) {
                                    this.deleteItem = this.sidebar.items.other[i];
                                    this.deleteItemIdx = i;
                                    break;
                                }
                            }
                        }
                    }
                    // hide/show delete button
                    if (this.is_action_enabled('delete')) {
                        if (!this.deleteItemShown) {
                            this.deleteItemShown = true;
                            // add delete item to sidebar's items
                            this.sidebar.items.other.splice(this.deleteItemIdx, 0, this.deleteItem);
                        }
                    } else
                    if (this.deleteItemShown) {
                        this.deleteItemShown = false;
                        // remove delete item from sidebar's items
                        this.sidebar.items.other.splice(this.deleteItemIdx, 1);
                    }
                }
            },
            reload: function() {
                var self = this;
                // run reinit_actions after reload finish
                return this._super.apply(this, arguments).done(function() {
                     self.reinit_actions();
                });
            },
            do_show: function() {
                var self = this;
                // run reinit_actions after do_show finish
                return this._super.apply(this, arguments).done(function() {
                     self.reinit_actions();
                });
            }
        });
    
    });
    

    【讨论】:

      【解决方案3】:

      我相信带有计算域的解决方案可以让这些情况变得更简单。

      您可以继承并覆盖物料清单表单。将不可见条件指向您将在其中创建验证的计算字段。请注意,将计算域添加到表单中是必要的,即使隐藏它也是如此。

      <xpath expr="//form[@string='Bill of Material']" position="attributes">
          <attribute name="attrs">
              {'invisible': [('show_bm_button', '=', False)]}
          </attribute>
          <field name="show_bm_button" invisible="1"/>
      </xpath>
      

      然后在python中覆盖对象并添加新的计算域。

      class ProductTemplate(models.Model):
          _inherit = 'product.template'
      
          show_bm_button = fields.Boolean(
                  compute='_compute_show_bm_button', 
                  readonly=False, store=False
              )
      
          # @api.depends('realman') #Just as a sample, if you have this field in this Model
          def _compute_show_bm_button(self):
              for record in self:
                  realman = self._context.get('realman') or True
                  if realman:
                      record.show_bm_button = True
                  else:
                      record.show_bm_button = False
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多