odoo fields_view_get創建動態視圖方法
odoo fields_view_get方法是一個比較有用比較靈活的廣泛,如果使用得當,可以做到一些常規方法無法實現的功能,本文列舉若干種用法。
openerp的視圖結構是以XML的格式存放於ir.ui.view表中,屬於靜態格式,設計之后就固定,
但可以通過在model中重寫fields_view_get函數,在視圖加載時修改arch屬性,動態修改視圖的結構
Odoo 開發中經常會遇到這樣的需求,對象中根據條件是否顯示一個字段。比如如果不是創建人,不不顯示客戶的聯系方式,Odoo 中如何實現呢?<一>domain在 odoo 中可以根據對象字段的值或者關系確定是否顯示一個字段。
動態 domain 的例子,根據選擇結構確定字段是否顯示。還有一種方式是,可以在 view 中,根據 states 的值確定字段是否顯示。
view 的state
動態視圖
用法一、 修改field的屬性:
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): #override of fields_view_get in order to replace the name field to product template if context is None: context={} res = super(product_product, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu) #check the current user in group_product_variant group_id = self.pool['ir.model.data'].get_object_reference(cr, uid, 'product', 'group_product_variant')[1] obj = self.pool.get('res.groups').browse(cr, uid, group_id, context=context) doc = etree.XML(res['arch']) if view_type == 'form': if obj and uid in [x.id for x in obj.users]: for node in doc.xpath("//field[@name='name']"): node.set('invisible', '1') node.set('required', '0') setup_modifiers(node, res['fields']['name']) #這行必須要有 for node in doc.xpath("//label[@string='Product Name']"): node.set('string','Product Template') else: for node in doc.xpath("//field[@name='product_tmpl_id']"): node.set('required','0') setup_modifiers(node, res['fields']['product_tmpl_id']) #這行必須要有 for node in doc.xpath("//field[@name='name']"): node.set('invisible', '0') setup_modifiers(node, res['fields']['name']) #這行必須要有 for node in doc.xpath("//label[@string='Product Template']"): node.set('string','Product Name') res['arch'] = etree.tostring(doc) return res
1
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): if context is None:context = {} res = super(rhwl_gene, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False) if res['type']=="form": id = res['id'] //根據id去取得資料,並進行判斷 if 條件成立: doc = etree.XML(res['arch']) doc.xpath("//form")[0].set("edit","false") res['arch']=etree.tostring(doc) return res
2
def fields_view_get(self, cr, uid, view_id=None,view_type='form',context=None,toolbar=False,submenu=False): ip_obj = self.pool.get('hr.rule.input') res = super(hr_inputs_editor,self).fields_view_get(cr,uid,view_id,view_type,context,toolbar,submenu) if view_type=='form': treev = res['fields']['line_ids']['views']['tree'] doc = etree.XML(treev['arch']) for node in doc.xpath("/tree/field"): name = node.get('name',False) if name.startswith('value'): name = name.replace('value','input') + '_code' cd = context.has_key(name) and context[name] or False if cd: ip_ids = ip_obj.search(cr,uid,[('code','=',cd)],limit=1,context=context) if ip_ids: text = ip_obj.read(cr,uid,ip_ids,['name'])[0]['name'] node.set('string',text) else: node.set('modifiers','{"tree_invisible":true}') treev['arch'] = etree.tostring(doc) return res
用法二、根據條件限制view是否可編輯(網上曾經有個人提出在指定日期內可以編輯,也可以參考下面的代碼實現)
@api.model def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False): if view_type == 'form': res['arch'] = self.fields_view_get_address(res['arch']) record = self.env['crm.lead'].browse(self._context.get('params').get('id')) # restrict modification and deletion of child ids if record.parent_id: res['arch'] = res['arch'][:6] + 'edit="false" delete="false" ' + res['arch'][6:] elif record.stage_id.id == 4: # restrict edition of Purchased Lead res['arch'] = res['arch'][:6] + 'edit="false" ' + res['arch'][6:] return res
用法三、給視圖動態增加field,下面的代碼是給某視圖動態增加一個field (product_id):
@api.model def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False): doc = etree.XML(res['arch']) summary = doc.xpath("//field[@name='product_id']") if len(summary): summary = summary[0] summary.addnext(etree.Element('field', {'name': 'product_id', 'string':'title of new field', 'nolabel':'0', })) res['arch'] = etree.tostring(eview) return res
用法四、給視圖增加一個page(跟用法三有些類似):
class product_product(osv.osv): _inherit = 'product.product' def fields_view_get(self, view_id=None, view_type='form', toolbar=False,submenu=False): """ Changes the view dynamically @param self: The object pointer. @return: New arch of view. """ ret_val = super(product_product, self).fields_view_get(view_id, view_type, toolbar,submenu) if view_type == 'form': doc = etree.XML(ret_val['arch'], parser=None, base_url=None) #要加入到視圖里的page _moves_arch_lst = """ <page string='Feature'> </page> """ first_node = doc.xpath("//page[@string='Sales']") if first_node and len(first_node)>0: #先把_moves_arch_lst轉成XML Node,然后加到查找到node中 feature_page = etree.XML(_moves_arch_lst) first_node.addnext(feature_page) ret_val['arch'] = etree.tostring(doc, encoding="utf-8") return ret_val
動態修改field的domain:
class account_voucher(osv.osv): _inherit = 'account.voucher' def fields_view_get(self, view_id=None, view_type=False, toolbar=False, submenu=False): """ Add domain 'allow_check_writting = True' on journal_id field and remove 'widget = selection' on the same field because the dynamic domain is not allowed on such widget """ if not context: context = {} res = super(account_voucher, self).fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu) doc = etree.XML(res['arch']) nodes = doc.xpath("//field[@name='journal_id']") # 檢查context是否有指定的標志(write_check) if context.get('write_check', False) : for node in nodes: # 動態修改 journal_id 這個field的domain node.set('domain', "[('type', '=', 'bank'), ('allow_check_writing','=',True),('your_field','=','value')]") # 把 widget 清空,原因在上面已經說了 node.set('widget', '') res['arch'] = etree.tostring(doc) return res
原文鏈接: http://www.odoogo.com/post/87/#comment-block