Odoo:_get_state()在xml视图中至少需要4个参数(4个给定)

时间:2016-08-23 07:08:54

标签: python openerp

这是mycode。我想在定义其模型类之前获取当前记录的id_employee:

def _get_state(self, cr, uid, context=None):
    idemployee = ""
    for adv in self.browse(cr, uid, ids, context):
        id_employee = adv.id_employee
        if id_employee is None:
            idemployee = _default_employee(self, cr, uid, context=None)
        else:
            idemployee = id_employee

    sql = " SELECT C.id AS id, C.sequence, C.name \
                   FROM wf_group_member A \
           LEFT JOIN wf_group B ON B.id = A.group_id \
           LEFT JOIN wf_process BB ON BB.id = B.process_id \
           LEFT JOIN wf_state C ON C.group_id = B.id \
           LEFT JOIN hr_employee D ON D.id = A.member_id \
           WHERE LOWER(code) = 'ca' AND member_id = %s ORDER BY sequence "
    res = []
    cr.execute(sql, [(idemployee)])
    ardata = cr.fetchall()
    for data in ardata:
        res.append((data[1], data[2]))
    return res

这是我在_get_state函数

之后放的模型类
class cashadvance(osv.osv):
    _name = 'ga.cashadvance'
    _columns = {
        'id_user'                   : fields.many2one('res.users', string='User', required=True, readonly=True),
        'state'                     : fields.selection(_get_state, 'Status', readonly=True),
        'id_employee'               : fields.many2one('hr.employee', string='Employee', required=True, readonly=True),
    }

当我调用_get_state函数时,它引发了错误:

Error details:
global name 'ids' is not defined
None" while parsing /opt/custom-addons/comben/views/cashadvance_view.xml:4, near
<record id="cashadvance_list" model="ir.ui.view">
            <field name="name">cashadvance_list</field>
            <field name="model">ga.cashadvance</field>
            <field name="arch" type="xml">
                <tree string="Cashadvance List">
                    <field name="id_employee"/>
                    <field name="category_id"/>
                    <field name="est_date_from" string="Est Date From"/>
                    <field name="est_date_to" string="Est Date To"/>
                    <field name="description"/>
                    <field name="state"/>
                </tree>
            </field>
        </record>

请帮助我,谢谢

2 个答案:

答案 0 :(得分:1)

_get_state必须是课程的一部分,你才能在课堂外使用它,你在那里传递的自我不被视为python self,即当前实例,它是被视为该函数的正常论证。

Python不会为你传递自我,让我偏离一点并重现你得到的错误。看看这段代码

def func(self,cr, uid, ids, context=None):
    pass

class func_test:
    def __init__(self):
        func(1, 1, 1, context=1)

a = func_test()

这是引发的错误(确保你用python2运行它)

Traceback (most recent call last):
  File "script.py", line 8, in <module>
    a = func_test()
  File "script.py", line 6, in __init__
    func(1, 1, 1, context=1)
TypeError: func() takes at least 4 arguments (4 given)

python实际上是正确的,即使它有误导性,该函数至少需要四个参数,因为context是一个关键字参数,并且在函数定义时已被填充,但它仍然缺少一个参数,因为该函数在外部一个类,所以通常称为self的第一个参数被视为一个普通参数(因为它是一个函数)而不是一个方法(类中的函数)。所以从左到右selfcruid将以1 1 1填写ids在这一点上,python会大声呼救,因为没有找到该参数的值,如果我们将该函数移动到类中并使用self.func调用它,则当前实例会自动为我们传递。

class func_test:
    def func(self,cr, uid, ids, context=None):
        pass

    def __init__(self):
        self.func(1, 1, 1, context=1)

a = func_test()

当然你仍然可以拥有func(self, 1, 1, 1, context=1),但那会破坏方法的目的

但请注意,python3比python2更智能,处理这种情况,这是一个python3追溯

Traceback (most recent call last):
  File "script.py", line 8, in <module>
    a = func_test()
  File "script.py", line 6, in __init__
    func(1, 1, 1, context=1)
TypeError: func() missing 1 required positional argument: 'ids'

它清楚地告诉我们,函数调用

中没有为ids提供任何值

所以回到Odoo你的代码看起来应该是这样的

from openerp.osv import osv, fields

class cashadvance(osv.osv):
    _name='comben.cashadvance'

    def _get_state(self, cr, uid, context=None):
        idemployee = ""

        ids = self.search(cr, uid, [], context=context) # you probably want to search for all the records
        for adv in self.browse(cr, uid, ids, context=context):
            id_employee = adv.id_employee
            if id_employee is None:
                idemployee = self._default_employee(cr, uid, ids, context=None) # might raise singleton error if more than one record is returned
            else:
                idemployee = id_employee.id

        sql = " SELECT C.id AS id, C.sequence, C.name \
                   FROM wf_group_member A \
           LEFT JOIN wf_group B ON B.id = A.group_id \
           LEFT JOIN wf_process BB ON BB.id = B.process_id \
           LEFT JOIN wf_state C ON C.group_id = B.id \
           LEFT JOIN hr_employee D ON D.id = A.member_id \
           WHERE LOWER(code) = 'ca' AND member_id = %s ORDER BY sequence "
        res = []
        cr.execute(sql, [(idemployee)])
        ardata = cr.fetchall()
        for data in ardata:
            res.append((data[1], data[2]))

       return res 

    _columns = {
        'id_user': fields.many2one('res.users', string='User', required=True, readonly=True),
        'state': fields.selection(_get_state, string='Status', readonly=True),
        'id_employee': fields.many2one('hr.employee', string='Employee', required=True, readonly=True),
    }

并将_default_employee移动到类主体中,因此您可以像这样调用它

self._default_employee(cr, uid, context=None) # python implicitly passes self for you

xml视图

<record id="cashadvance_list" model="ir.ui.view">
  <field name="name">cashadvance list</field>
  <field name="model">comben.cashadvance</field>
  <field name="arch" type="xml">
    <tree string="Cashadvance List">
      <field name="id_employee"/>
      <field name="id_user"/>
      <field name="state"/>
    </tree>
  </field>
</record>

答案 1 :(得分:0)

在这种情况下,你想要这个:

def _get_state(self, cr, uid, ids, context=None):
        current_record=self.browse(cr, uid, ids)
        idemployee = current_record[0].id_employee

    sql = " SELECT C.id AS id, C.sequence, C.name \
                   FROM wf_group_member A \
           LEFT JOIN wf_group B ON B.id = A.group_id \
           LEFT JOIN wf_process BB ON BB.id = B.process_id \
           LEFT JOIN wf_state C ON C.group_id = B.id \
           LEFT JOIN hr_employee D ON D.id = A.member_id \
           WHERE LOWER(code) = 'ca' AND member_id = %s ORDER BY sequence "
    res = []
    cr.execute(sql, [(idemployee)])
    ardata = cr.fetchall()
    for data in ardata:
        res.append((data[1], data[2]))
    return res