zoukankan      html  css  js  c++  java
  • openerp经典收藏 字段定义详解(转载)

    字段定义详解

    原文地址:
    http://shine-it.net/index.php/topic,2159.0.html
    http://blog.sina.com.cn/s/blog_57ded94e01014pm9.html

    OpenERP对象支持的字段类型有,基础类型:char, text, boolean, integer, float, date, time, datetime, binary;复杂类型:selection, function, related;关系类型:one2one, one2many, many2one, many2many。下面逐一说明。
    boolean: 布尔型(true, false)
    integer: 整数。
    float: 浮点型,如 'rate' : fields.float('Relative Change rate',digits=(12,6)), digits定义整数部分和小数部分的位数。
    char: 字符型,size属性定义字符串长度。
    text: 文本型,没有长度限制。
    date: 日期型
    datetime: 日期时间型
    binary: 二进制型
    function: 函数型,该类型的字段,字段值由函数计算而得,不存储在数据表中。其定义格式为:
    fields.function(fnct, arg=None, fnct_inv=None, fnct_inv_arg=None, type='float', fnct_search=None, obj=None, method=False, store=True)
    · type 是函数返回值的类型。
    · method 为True表示本字段的函数是对象的一个方法,为False表示是全局函数,不是对象的方法。如果method=True,obj指定method的对象。
    · fcnt 是函数或方法,用于计算字段值。如果method = true, 表示fcnt是对象的方法,其格式如下:def fnct(self, cr, uid, ids, field_name, args, context),否则,其格式如下:def fnct(cr, table, ids, field_name, args, context)。ids是系统传进来的当前存取的record id。field_name是本字段名,当一个函数用于多个函数字段类型时,本参数可区分字段。args是'arg=None'传进来的参数。
    · fcnt_inv 是用于写本字段的函数或方法。如果method = true, 其格式是:def fcnt_inv(self, cr, uid, ids, field_name, field_value, args, context),否则格式为:def fcnt_inv(cr, table, ids, field_name, field_value, args, context)
    · fcnt_search 定义该字段的搜索行为。如果method = true, 其格式为:def fcnt_search(self, cr, uid, obj, field_name, args),否则格式为:def fcnt_search(cr, uid, obj, field_name, args)
    · store 表示是否希望在数据库中存储本字段值,缺省值为False。不过store还有一个增强形式,格式为 store={'object_name':(function_name,['field_name1','field_name2'],priority)} ,其含义是,如果对象'object_name'的字段['field_name1','field_name2']发生任何改变,系统将调用函数function_name,函数的返回结果将作为参数(arg)传送给本字段的主函数,即fnct。

    selection: 下拉框字段。定义一个下拉框,允许用户选择值。如:'state': fields.selection((('n','Unconfirmed'),('c','Confirmed')),'State', required=True),这表示state字段有两个选项('n','Unconfirmed')和('c','Confirmed')。

    one2one: 一对一关系,格式为:fields.one2one(关联对象Name, 字段显示名, ... )。在V5.0以后的版本中不建议使用,而是用many2one替代。
    many2one: 多对一关系,格式为:fields.many2one(关联对象Name, 字段显示名, ... )。可选参数有:ondelete,可选值为"cascade"和"null",缺省值为"null",表示one端的record被删除后,many端的record是否级联删除。

    one2many: 一对多关系,格式为:fields.one2many(关联对象Name, 关联字段, 字段显示名, ... ),例:'address': fields.one2many('res.partner.address', 'partner_id', 'Contacts')。

    many2many: 多对多关系。例如:
        'category_id':fields.many2many('res.partner.category','res_partner_category_rel','partner_id','category_id','Categories'),
    表示以多对多关系关联到对象res.partner.category,关联表为'res_partner_category_rel',关联字段为'partner_id'和'category_id'。当定义上述字段时,OpenERP会自动创建关联表为'res_partner_category_rel',它含有关联字段'partner_id'和'category_id'。

    reference: 引用型,格式为:fields.reference(字段名, selection, size, ... )。其中selection是: 1)返回tuple列表的函数,或者 2)表征该字段引用哪个对象(or model)的tuples列表。reference字段在数据库表中的存储形式是(对象名,ID),如(product.product,3)表示引用对象product.product(数据表product_product)中id=3的数据。reference的例子:
        def _links_get(self, cr, uid):
            cr.execute('select object,name from res_request_link order by priority')
            return cr.fetchall()

        ...
        'ref':fields.reference('Document Ref 2', selection=_links_get, size=128),
        ...
    上例表示,字段ref可以引用哪些对象类型的resource,可引用的对象类型从下拉框选择。下拉框的选项由函数_links_get返回,是(object,name)对的列表,如[("product.product","Product"), ("account.invoice","Invoice"), ("stock.production.lot","Production Lot")] 。

    related: 关联字段,表示本字段引用关联表中的某字段。格式为:fields.related(关系字段,引用字段,type, relation, string, ...),关系字段是本对象的某字段(通常是one2many or many2many),引用字段是通过关系字段关联的数据表的字段,type是引用字段的类型,如果type是many2one or many2many, relation指明关联表。例子如下:
            'address': fields.one2many('res.partner.address', 'partner_id', 'Contacts'),
            'city':fields.related('address','city',type='char', string='City'),
            'country':fields.related('address','country_id',type='many2one', relation='res.country', string='Country'),

    这里,city引用address的city字段,country引用address的country对象。在address的关联对象res.partner.address中,country_id是many2one类型的字段,所以type='many2one', relation='res.country'。

    property: 属性字段,下面以具体例子解说property字段类型。
    'property_product_pricelist': fields.property('product.pricelist', type='many2one', relation='product.pricelist',string="Sale Pricelist", method=True, view_load=True, group_name="Pricelists Properties")
    这个例子表示,本对象通过字段'property_product_pricelist'多对一(type='many2one')关联到对象product.pricelist(relation='product.pricelist')。和many2one字段类型不同的是,many2one字段会在本对象中创建数据表字段'property_product_pricelist',property字段类型不会创建数据表字段'property_product_pricelist'。property字段类型会从数据表ir.property中查找name='property_product_pricelist'(即字段定义中的'product.pricelist'加上前缀property,并将"."替换成"_"作为name)且company_id和本对象相同的记录,从该记录的value字段(value字段类型为reference)查得关联记录,如(product.pricelist,1),表示本对象的resource多对一关联到对象product.pricelist的id=1的记录。也就是说,property字段类型通过ir.property间接多对一关联到别的对象。
        property字段类型基本上和many2one字段类型相同,但是有两种情况优于many2one字段。其一是,例如,当有多条记录通过ir.property的name='property_product_pricelist'的记录关联到记录(product.pricelist,1),此时,如果希望将所有关联关系都改成关联到记录(product.pricelist,2)。如果是many2one类型,不写代码,很难完成此任务,是property字段的话,只要将ir.property中的value值(product.pricelist,1)改成(product.pricelist,2),则所有关联关系都变了。修改ir.property的value值可以在系统管理下的菜单Configuration --> Properties中修改。其二是,例如,同一业务伙伴,但希望A公司的用户进来看到的该业务伙伴价格表为pricelistA,B公司的用户进来看到的该业务伙伴价格表为pricelistB,则many2one类型达不到该效果。property类型通过ir.property中的记录关联时加上了company_id的条件,因此可以使得不同公司的员工进来看到不同的关联记录。
        由于property类型通过ir.property关联,因此,每个property类型的字段都必须在ir.property中有一条关联记录。这可以在安装时导入该条记录,参考代码如下:
        <record model="ir.property" id="property_product_pricelist">
            <field name="name">property_product_pricelist</field>
            <field name="fields_id" search="[('model','=','res.partner'), ('name','=','property_product_pricelist')]"/>
            <field name="value" eval="'product.pricelist,'+str(list0)"/>
        </record>

    字段定义的参数
        字段定义中可用的参数有, change_default,readonly,required,states,string,translate,size,priority,domain,invisible,context,selection。
    change_default:别的字段的缺省值是否可依赖于本字段,缺省值为:False。例子(参见res.partner.address),
        'zip': fields.char('Zip', change_default=True, size=24),

    这个例子中,可以根据zip的值设定其它字段的缺省值,例如,可以通过程序代码,如果zip为200000则city设为“上海”,如果zip为100000则city为“北京”。

    readonly: 本字段是否只读,缺省值:False。
    required: 本字段是否必须的,缺省值:False。
    states: 定义特定state才生效的属性,格式为:{'name_of_the_state': list_of_attributes},其中list_of_attributes是形如[('name_of_attribute', value), ...]的tuples列表。例子(参见account.transfer):
        'partner_id': fields.many2one('res.partner', 'Partner', states={'posted':[('readonly',True)]}),

    string: 字段显示名,任意字符串。
    translate: 本字段值(不是字段的显示名)是否可翻译,缺省值:False。
    size: 字段长度。
    priority
    domain: 域条件,缺省值:[]。在many2many和many2one类型中,字段值是关联表的id,域条件用于过滤关联表的record。例子:
    'default_credit_account_id': fields.many2one('account.account', 'Default Credit Account', domain="[('type','!=','view')]"),

    本例表示,本字段关联到对象('account.account')中的,type不是'view'的record。

    invisible: 本字段是否可见,即是否在界面上显示本字段,缺省值True。
    selection: 只用于reference字段类型,参见前文reference的说明。
     
    ----------------------------------------------------------------------------------------------------------------------
    老肖辛苦了,function字段解析得很好.. :)

    1.对于字段定义我看到fields.py里面还有个
    integer_big 在ORM里面对应的是'int8',不过好像没有过多的介绍了,在其他模块里面也不见到使用
    平时我们的在PostgreSQL里面的integer虽然也够长的了..
    引用
    integer 4 字节 常用的整数 -2147483648 到 +2147483647
     

    不过好像真没见过使用

    2.selection:他也有function的store属性,作用也是在数据库里面保存这一字段,不过就算不显式写这个属性也会保存的...代码addonsaccount_voucheraccount.py。另外一个问题就是function的store=true有没有意义呢,不是每次读取这个function就会执行里面的方法,那么还储存在数据库里面有什么作用?

    3.change_default:貌似有bug曾经测试过,如果一个view里面设了两个字段为change_default就不出来了。

    4.related:这个字段在之前partner源码分析的时候看过,继承自function,就像一个partner对应多个address,他会默认取第一个作为在partner tree里面显示出来的。
    5.关于property,我看不明白这段代码
    <field name="value" eval="'product.pricelist,'+str(list0)"/>
    这个list0什么意思呢?
    « 最后编辑时间: 九月 16, 2010, 03:30:17 下午 作者 Joshua »

    ----------------------------------------------------------------------------------------------------------------------
    谢谢 Joshua的补充!
    > 另外一个问题就是function的store=true有没有意义呢,不是每次读取这个function就会执行里面的方法,那么还储存在数据库里面有什么作用?
    我的理解是store=true可以将每次函数计算的结果存储到数据库中,这样有两个好处,一是便于DBA从数据库查看数据;二是非OpenERP的软件可以直接访问数据库共享数据。另外补充一点,fcnt_inv不限于写入本对象的数据表,更经常的情形是写入别的对象,甚至同时写入多个对象的数据表。

    > <field name="value" eval="'product.pricelist,'+str(list0)"/>
    前文说过,value字段类型为reference,即形如(product.pricelist,1)的值。这一行就是计算value的值,形如(product.pricelist,list0),list0(经导入后其值是数字)是引用的product.pricelist中的一条记录的id,如下。
            <record id="list0" model="product.pricelist">
                <field name="name">Default Purchase Pricelist</field>
                <field name="type">purchase</field>
            </record>
    也就是说,在<field name="value" eval="'product.pricelist,'+str(list0)"/>之前,必须先有上述导入id="list0"的代码行。
    ----------------------------------------------------------------------------------------------------------------------

    关于field.function我有其他问题,例如
    sale这个模块里面的

    程序代码: [选择]
    'amount_untaxed': fields.function(_amount_all, method=True, digits=(16, int(config['price_accuracy'])), string='Untaxed Amount',
                store = {
                    'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line'], 10),
                    'sale.order.line': (_get_order, ['price_unit', 'tax_id', 'discount', 'product_uom_qty'], 10),
                },
                multi='sums'),
    

    _get_order

    程序代码: [选择]
        def _get_order(self, cr, uid, ids, context={}):
            result = {}
            for line in self.pool.get('sale.order.line').browse(cr, uid, ids, context=context):
                result[line.order_id.id] = True
            return result.keys()
    

    问题来了上面的代码是在sale.order里面的,他是根据sale.order.line的变化。而触发调不调用 _amount_all。但是_get_oeder里面的ids究竟是从何而来呢?是自动对应这个sale.order的sale.order.line吗?这里的_amount_all是任意一个sale.order.line变化就会触发,还是某个sale.order的sale.order.line变化才促发呢?

    ----------------------------------------------------------------------------------------------------------------------

    这个问题太深入了,俺没深入调查源代码,只是凭经验回答。_get_order里面的ids从界面上来,是界面上当前Order的order.line的ids。因此,当前界面上的sale.order的任意一个 sale.order.line的变化,将会触发_amount_all的调用。
    ----------------------------------------------------------------------------------------------------------------------
    sale.order.line有个比较讨厌的地方就是,他有单独的menu。这样用户可能不在订单header界面进去而是直接修改订单行。
    ----------------------------------------------------------------------------------------------------------------------


    估计这个store参数就是为了解决这个问题的



  • 相关阅读:
    Smart Client Architecture and Design Guide
    Duwamish密码分析篇, Part 3
    庆贺发文100篇
    .Net Distributed Application Design Guide
    New Introduction to ASP.NET 2.0 Web Parts Framework
    SPS toplevel Site Collection Administrators and Owners
    来自Ingo Rammer先生的Email关于《Advanced .Net Remoting》
    The newsletter published by Ingo Rammer
    深度探索.Net Remoting基础架构
    信道、接收器、接收链和信道接受提供程序
  • 原文地址:https://www.cnblogs.com/cnshen/p/3177564.html
Copyright © 2011-2022 走看看