Odoo中文社区可以通过以下三个域名访问:shine-it.net , odoocn.org,odoo.net.cn

原论坛用户的基本信息和发帖这里都予以保留,请注意:原论坛用户无需重新注册新用户,但是您的密码需要重置

开发人员可以登录gitter讨论组: http://gitter.im/odoo-china/Talk, 需要github账号

如果您登录系统碰到问题,请在微信公众号留言:

Default_get函数为什么会执行两次?



  • python
    [code]
    def default_get(self, cr, uid, fields_list, context=None):
        if 'name' in fields_list:
            trial_account = self.pool.get('ir.sequence').get(cr, uid, 'web.account.trial')
            res.update({'name': trial_account})
    def button_confirm(self, cr, uid, ids, context=None):
        return True
    [/code]
    XML
    [code]
    …………
    <field name="name" placeholder="请在此填入账户名称"/>
    <footer>
          <button name="button_confirm" type="object" string="确认" class="oe_highlight"/>
                  or
          <button string="Cancel" class="oe_link" special="cancel" />
    </footer>
    [/code]
    新建对话框的时候,name默认获得一个新的帐号,如T00001,是一个自增帐号。
    现在的问题是,新建对话框后,name显示T00001,但是点击“确认”按钮后,name就变成T00002了,保存在数据库中的也是T00002,T00001只是显示一下,没有被保存住。
    测试了一下,发现新建的时候,default_get运行了一次,点击确认关闭对话框的时候,default_get又运行了一次,或以再次抓取了一个新的name。
    请问为什么default_get会运行两次呢?或者有什么办法解决这个问题?
    谢谢!



  • python
    [code]
    def default_get(self, cr, uid, fields_list, context=None):
        if 'name' in fields_list:
            trial_account = self.pool.get('ir.sequence').get(cr, uid, 'web.account.trial')
            res.update({'name': trial_account})
    def button_confirm(self, cr, uid, ids, context=None):
        return True
    [/code]
    XML
    [code]
    …………
    <field name="name" placeholder="请在此填入账户名称"/>
    <footer>
          <button name="button_confirm" type="object" string="确认" class="oe_highlight"/>
                  or
          <button string="Cancel" class="oe_link" special="cancel" />
    </footer>
    [/code]
    新建对话框的时候,name默认获得一个新的帐号,如T00001,是一个自增帐号。
    现在的问题是,新建对话框后,name显示T00001,但是点击“确认”按钮后,name就变成T00002了,保存在数据库中的也是T00002,T00001只是显示一下,没有被保存住。
    测试了一下,发现新建的时候,default_get运行了一次,点击确认关闭对话框的时候,default_get又运行了一次,或以再次抓取了一个新的name。
    请问为什么default_get会运行两次呢?或者有什么办法解决这个问题?
    谢谢!



  • 以代码回复:

    第一次 调用 default_get 是,当你点击 button new 的时候:

    参见view_form.js

    [code]
        on_button_new: function() {
            var self = this;
            this.to_edit_mode();
            return $.when(this.has_been_loaded).then(function() {
                if (self.can_be_discarded()) {
                    return self.load_defaults();
                }
            });
        },


        load_defaults: function () {
            var self = this;
            var keys = _.keys(this.fields_view.fields);
            if (keys.length) {
                return this.dataset.default_get(keys).then(function(r) {
                    self.trigger('load_record', r);
                });
            }
            return self.trigger('load_record', {});
        },

    [/code]

    var keys = _.keys(this.fields_view.fields) 这样会去取所有字段的默认值。

    第二次调用 default_get 是  orm.py  的 create 方法:

    [code]
        def create(self, cr, user, vals, context=None):
    """
            vals = self._add_missing_default_values(cr, user, vals, context)
    """
    [/code]

    那么我们来看一下 _add_missing_default_values 函数:
    [code]
        def _add_missing_default_values(self, cr, uid, values, context=None):
            missing_defaults = []
            avoid_tables = [] # avoid overriding inherited values when parent is set
            for tables, parent_field in self._inherits.items():
                if parent_field in values:
                    avoid_tables.append(tables)
            for field in self._columns.keys():
                if not field in values:
                    missing_defaults.append(field)
            for field in self._inherit_fields.keys():
                if (field not in values) and (self._inherit_fields[field][0] not in avoid_tables):
                    missing_defaults.append(field)

            if len(missing_defaults):
                # override defaults with the provided values, never allow the other way around
                defaults = self.default_get(cr, uid, missing_defaults, context)

    。。。。。。
    [/code]

    以上,missing_defaults 就是需要获取默认值的列,那么为什么有些字段会重复取值呢, 原因是 create 方法参数 vals 中仅仅保持了 form view 中定义的字段,而第一次取的字段值,可能会因为 form view 中没有对于字段,而被丢弃了。所以,在 create 方法中,会认为该字段没有赋值,因此又会添加到 missing_defaults  再取一次默认值。


    原因找到了,解决方法就不难了吧。

    其中一种BT的方法是,在 FORM VIEW 定义一个 field invisable = True 的字段,隐藏带上来。


  • 管理员

    [quote author=wangbuke link=topic=9918.msg19783#msg19783 date=1377068877]
    ......
    那么为什么有些字段会重复取值呢, 原因是 create 方法参数 vals 中仅仅保持了 form view 中定义的字段,而第一次取的字段值,可能会因为 form view 中没有对于字段,而被丢弃了。所以,在 create 方法中,会认为该字段没有赋值,因此又会添加到 missing_defaults  再取一次默认值。
    [/quote]

    感谢buke的精彩回复,这里我举个例子说一下为什么form view的字段会被丢弃的原因:
    例如字段定义[b]readonly[/b]了,那样就会出现上述buke所描述的情形。

    待lz分析下自己问题的出现原因。



  • name已经定义了,第二次不该调用



  • 非常感谢buke的详细解释,也感谢Joshua的解决方案,将name字段的readonly属性取消后,确实没有问题了。
    另外,上周没来得及上论坛,我自己用了一个笨方法解决问题,就是用sql去查询数据库中已有的name的最大值,如查出来是T00010, +1后在存回去。这样虽然form view字段被丢弃,但是因为是从数据库查询,所以不管default_get执行多少次都不会有问题。


登录后回复
 

与 Odoo 中文社区 的连接断开,我们正在尝试重连,请耐心等待