zoukankan      html  css  js  c++  java
  • openerp学习笔记 对象间关系【多对一(一对一)、一对多(主细结构)、多对多关系、自关联关系(树状结构)】

    1.多对一(一对一)关系:采购单与供应商之间的关系

    'partner_id':fields.many2one('res.partner', 'Supplier', required=True, states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)],'done':[('readonly',True)]},
    change_default=True, track_visibility='always'),

    典型的录入界面:

    2.一对多(主细结构)关系:采购单主表与采购单明细表之间的关系

    'order_line': fields.one2many('purchase.order.line', 'order_id', 'Order Lines', states={'approved':[('readonly',True)],'done':[('readonly',True)]}),

    典型的录入界面:

    对应的XML定义:

                            <page string="Purchase Order">
                                <field name="order_line">
                                    <tree string="Purchase Order Lines" editable="bottom">
                                        <field name="product_id" on_change="onchange_product_id(parent.pricelist_id,product_id,0,product_uom,parent.partner_id, parent.date_order,parent.fiscal_position,date_planned,name,price_unit,context)"/>
                                        <field name="name"/>
                                        <field name="date_planned"/>
                                        <field name="company_id" groups="base.group_multi_company" widget="selection"/>
                                        <field name="account_analytic_id" groups="purchase.group_analytic_accounting" domain="[('type','not in',('view','template'))]"/>
                                        <field name="product_qty" on_change="onchange_product_id(parent.pricelist_id,product_id,product_qty,product_uom,parent.partner_id,parent.date_order,parent.fiscal_position,date_planned,name,price_unit,context)"/>
                                        <field name="product_uom" groups="product.group_uom" on_change="onchange_product_uom(parent.pricelist_id,product_id,product_qty,product_uom,parent.partner_id, parent.date_order,parent.fiscal_position,date_planned,name,price_unit,context)"/>
                                        <field name="price_unit"/>
                                        <field name="taxes_id" widget="many2many_tags" domain="[('parent_id','=',False),('type_tax_use','!=','sale')]"/>
                                        <field name="price_subtotal"/>
                                    </tree>
                                </field>
                                <group class="oe_subtotal_footer oe_right">
                                    <field name="amount_untaxed" widget="monetary" options="{'currency_field': 'currency_id'}"/>
                                    <field name="amount_tax" widget="monetary" options="{'currency_field': 'currency_id'}"/>
                                    <div class="oe_subtotal_footer_separator oe_inline">
                                        <label for="amount_total"/>
                                        <button name="button_dummy"
                                            states="draft" string="(update)" type="object" class="oe_edit_only oe_link"/>
                                    </div>
                                    <field name="amount_total" nolabel="1" class="oe_subtotal_footer_separator" widget="monetary" options="{'currency_field': 'currency_id'}"/>
                                </group>
                                <div class="oe_clear"/>
                                <field name="notes" class="oe_inline" placeholder="Terms and conditions..."/>
                            </page>

    反过来,采购单明细与采购单主表之间为多对一关系

    'order_id': fields.many2one('purchase.order', 'Order Reference', select=True, required=True, ondelete='cascade'),

    其中 ondelete='cascade' 表示开启级联删除,即删除采购单主表时自动删除采购单明细表。

    3.多对多关系:客户与客户类型之间的关系,自动生成关联表 res_partner_res_partner_category_rel

    'category_id': fields.many2many('res.partner.category', id1='partner_id', id2='category_id', string='Tags'),

    典型的录入界面1:

    对应的XML定义:
      <field name="category_id" widget="many2many_tags" placeholder="Tags..."/>

    典型的录入界面2:

    对应的XML定义:

      <page string="库位操作范围">
        <field name="location_ids" nolabel="1" />
      </page>

    4.自关联关系:OpenERP客户与联系人之间的关系,res.partner 与 res.partner 自关联产生 many2one 关系(parent_id)和  one2many 关系(child_ids

    class res_partner(osv.osv, format_address):
        _description = 'Partner'
        _name = "res.partner"

        # indirection to avoid passing a copy of the overridable method when declaring the function field
        _commercial_partner_id = lambda self, *args, **kwargs: self._commercial_partner_compute(*args, **kwargs)

        _order = "name"
        _columns = {
            'name': fields.char('Name', size=128, required=True, select=True),
            'date': fields.date('Date', select=1),
            'title': fields.many2one('res.partner.title', 'Title'),
            'parent_id': fields.many2one('res.partner', 'Related Company'),
            'child_ids': fields.one2many('res.partner', 'parent_id', 'Contacts', domain=[('active','=',True)]), # force "active_test" domain to bypass _search() override   
            'ref': fields.char('Reference', size=64, select=1),
            'lang': fields.selection(_lang_get, 'Language',
                help="If the selected language is loaded in the system, all documents related to this contact will be printed in this language. If not, it will be English."),
            'tz': fields.selection(_tz_get,  'Timezone', size=64,
                help="The partner's timezone, used to output proper date and time values inside printed reports. "
                     "It is important to set a value for this field. You should use the same timezone "
                     "that is otherwise used to pick and render date and time values: your computer's timezone."),
            'tz_offset': fields.function(_get_tz_offset, type='char', size=5, string='Timezone offset', invisible=True),
            'user_id': fields.many2one('res.users', 'Salesperson', help='The internal user that is in charge of communicating with this contact if any.'),
            'vat': fields.char('TIN', size=32, help="Tax Identification Number. Check the box if this contact is subjected to taxes. Used by the some of the legal statements."),
            'bank_ids': fields.one2many('res.partner.bank', 'partner_id', 'Banks'),
            'website': fields.char('Website', size=64, help="Website of Partner or Company"),
            'comment': fields.text('Notes'),
            'category_id': fields.many2many('res.partner.category', id1='partner_id', id2='category_id', string='Tags'),
            'credit_limit': fields.float(string='Credit Limit'),
            'ean13': fields.char('EAN13', size=13),
            'active': fields.boolean('Active'),
            'customer': fields.boolean('Customer', help="Check this box if this contact is a customer."),
            'supplier': fields.boolean('Supplier', help="Check this box if this contact is a supplier. If it's not checked, purchase people will not see it when encoding a purchase order."),
            'employee': fields.boolean('Employee', help="Check this box if this contact is an Employee."),
            'function': fields.char('Job Position', size=128),
            'type': fields.selection([('default', 'Default'), ('invoice', 'Invoice'),
                                       ('delivery', 'Shipping'), ('contact', 'Contact'),
                                       ('other', 'Other')], 'Address Type',
                help="Used to select automatically the right address according to the context in sales and purchases documents."),
            'street': fields.char('Street', size=128),
            'street2': fields.char('Street2', size=128),
            'zip': fields.char('Zip', change_default=True, size=24),
            'city': fields.char('City', size=128),
            'state_id': fields.many2one("res.country.state", 'State'),
            'country_id': fields.many2one('res.country', 'Country'),
            'country': fields.related('country_id', type='many2one', relation='res.country', string='Country',
                                      deprecated="This field will be removed as of OpenERP 7.1, use country_id instead"),
            'email': fields.char('Email', size=240),
            'phone': fields.char('Phone', size=64),
            'fax': fields.char('Fax', size=64),
            'mobile': fields.char('Mobile', size=64),
            'birthdate': fields.char('Birthdate', size=64),
            'is_company': fields.boolean('Is a Company', help="Check if the contact is a company, otherwise it is a person"),
            'use_parent_address': fields.boolean('Use Company Address', help="Select this if you want to set company's address information  for this contact"),
            # image: all image fields are base64 encoded and PIL-supported
            'image': fields.binary("Image",
                help="This field holds the image used as avatar for this contact, limited to 1024x1024px"),
            'image_medium': fields.function(_get_image, fnct_inv=_set_image,
                string="Medium-sized image", type="binary", multi="_get_image",
                store={
                    'res.partner': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
                },
                help="Medium-sized image of this contact. It is automatically "
                     "resized as a 128x128px image, with aspect ratio preserved. "
                     "Use this field in form views or some kanban views."),
            'image_small': fields.function(_get_image, fnct_inv=_set_image,
                string="Small-sized image", type="binary", multi="_get_image",
                store={
                    'res.partner': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
                },
                help="Small-sized image of this contact. It is automatically "
                     "resized as a 64x64px image, with aspect ratio preserved. "
                     "Use this field anywhere a small image is required."),
            'has_image': fields.function(_has_image, type="boolean"),
            'company_id': fields.many2one('res.company', 'Company', select=1),
            'color': fields.integer('Color Index'),
            'user_ids': fields.one2many('res.users', 'partner_id', 'Users'),
            'contact_address': fields.function(_address_display,  type='char', string='Complete Address'),

            # technical field used for managing commercial fields
            'commercial_partner_id': fields.function(_commercial_partner_id, type='many2one', relation='res.partner', string='Commercial Entity'),
            'create_uid': fields.many2one('res.users', u"创建用户", invisible=False, readonly=True), #需要在记录中读取该字段或者在视图、打印中显示该字段时,对象中必须包含
        }

    5.自关联关系(树状结构,无限级):产品类别与父级类别之间的关系,product.category 与 product.category 自关联产生 many2one 关系(parent_id)和  one2many 关系(child_id

    class product_category(osv.osv):

        def name_get(self, cr, uid, ids, context=None):
            if isinstance(ids, (list, tuple)) and not len(ids):
                return []
            if isinstance(ids, (long, int)):
                ids = [ids]
            reads = self.read(cr, uid, ids, ['name','parent_id'], context=context)
            res = []
            for record in reads:
                name = record['name']
                if record['parent_id']:
                    name = record['parent_id'][1]+' / '+name
                res.append((record['id'], name))
            return res

        def _name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
            res = self.name_get(cr, uid, ids, context=context)
            return dict(res)

        _name = "product.category"
        _description = "Product Category"
        _columns = {
            'name': fields.char('Name', size=64, required=True, translate=True, select=True),
            'complete_name': fields.function(_name_get_fnc, type="char", string='Name'),
            'parent_id': fields.many2one('product.category','Parent Category', select=True, ondelete='cascade'),
            'child_id': fields.one2many('product.category', 'parent_id', string='Child Categories'),
            'sequence': fields.integer('Sequence', select=True, help="Gives the sequence order when displaying a list of product categories."),
            'type': fields.selection([('view','View'), ('normal','Normal')], 'Category Type', help="A category of the view type is a virtual category that can be used as the parent of another category to create a hierarchical structure."),
            'parent_left': fields.integer('Left Parent', select=1),
            'parent_right': fields.integer('Right Parent', select=1),
        }

        _defaults = {
            'type' : lambda *a : 'normal',
        }

        _parent_name = "parent_id"
        _parent_store = True
        _parent_order = 'sequence, name'
        _order = 'parent_left'

        def _check_recursion(self, cr, uid, ids, context=None):
            level = 100
            while len(ids):
                cr.execute('select distinct parent_id from product_category where id IN %s',(tuple(ids),))
                ids = filter(None, map(lambda x:x[0], cr.fetchall()))
                if not level:
                    return False
                level -= 1
            return True

        _constraints = [
            (_check_recursion, 'Error ! You cannot create recursive categories.', ['parent_id'])
        ]
        def child_get(self, cr, uid, ids):
            return [ids]

    product_category()

  • 相关阅读:
    打印对象的 “精心骗局”
    js继承(自备水,这非常干货)
    递归实现深拷贝( 只要学过js递归,看不懂找我包会 )
    PuTTY SSH 使用证书免密码登录
    git 使用
    php socket通信的简单实现
    基于PHP实现短信验证码接口的方法
    PHP实现页面静态化的简单方法分享
    Yii2使用数据库操作汇总(增删查改、事务)
    PHP 获取当前页面的URL信息
  • 原文地址:https://www.cnblogs.com/cnshen/p/3164741.html
Copyright © 2011-2022 走看看