odoo框架开发汇总

1.创建模块命令

    示例:D:\env\python\python.exe D:\odoo-14\server\odoo-bin scafflod module_name D:\odoo-  14\server\addons

2.后端返回视图

   写法1: 找视图id,返回动作窗口字典,方法与视图示例如下:    

def open_tree_or_form(self):
    res_ids = self.env['qc.dmr'].sudo().search([('name', '=', '203382')])
    tree_view_id = self.env.ref('xunde_quality_contorl.qc_dmr_tree_view')
    form_view_id = self.env.ref('xunde_quality_control.qc_dmr_form_view')
    if len(res_ids) == 1:
       return {
            'name' _(质检),
            'view_mode': 'form',
            'res_model': 'qc.dmr',
            'views': [[form_view_id.id, 'form']],
            'type': 'ir.actions.act_window',
            'res_id': dmr_ids.id,
            'target': 'current',
            'context': {}
       }
    elif len(res_ids) > 1:
       return {
            'name' _(质检),
            'view_mode': 'tree',
            'res_model': 'qc.dmr',
            'views': [(tree_view_id.id, 'tree'), (form_view_id.id, 'form')],
            'type': 'ir.actions.act_window',
            'domain': [('id', 'in', res_ids.ids)],
            'target': 'current',
            'context': {}
       }
    else:
        return {'type': 'ir.actions.act_window_close'}

<...>

写法2:找特定action的id,并在方法里返回,示例代码如下:

def open_tree_or_form(self):
    ...
    action = self.env['ir.actions.act_window']._for_xml_id(f"account.{action.name}")
    action['context'] = {}
    action['domain'] = [(...)]
    action['name'] = _("...")
    action['views'] = [[False, 'form']]
    ...
    return action

3. 瞬态视图

   用途:可以用于审批驳回功能,可以用于导入文件向导, 一般是在视图添加按钮,通过按钮打开瞬态视图,瞬态视图模型,一般有个default_get函数和关联主表的字段,示例代码如下:


...
# 瞬态模型示例
from odoo import models, fields, api, _
from odoo.exceptions import UserError


class TransientModelExample(models.TransientModel):
     _name = 'transientmodel.example'
     _description = '瞬态模型示例'
    
     def default_get(self, fields_list):
         ....
     
     origin_id = fields.Many2one(...)

     def action_reject(self):
         ...

 4.视图继承

   利用xpath语法,对原有视图进行修改,不建议过多继承视图,因为会导致视图继承混乱,后期不好维护。



    



   1



   

5.搜索设置默认分组

 需求:打开tree视图,就有默认分组,修改搜索视图和客户端动作的上下文,示例代码如下:



    
    
    
    
       
    
    
       
    




    ...
    ...
    tree,form
    
    
    {'search_default_by_parent_id':1}

6. 字段与按钮在一行

   实现字段与按钮在一行,代码如下:


7._fields_view_get函数

       该函数是视图加载时会自动调用的函数,使用场景示例:根据权限组动态控制字段的属性,包括可见性、只读性等,示例代码如下:

@api.model
def _fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
    result = super(XdBusinessExample,self)._fields_view_get(view_id=view_id,
                                                            view_type=view_type,
                                                            toolbar=toolbar, 
                                                            submenu=submenu)
    if view_type == 'form':
        if self.env.user.has_group('xd.business.purchase_group'):
           doc = etree.XML(result.get('arch', ''))
           page_purchase = doc.xpath('page[@name='purchase']')
           for i in page_purchase:
               i.set('invisible', '1')
           result['arch'] = etree.tostring(doc)
    return result
 

8. binary转附件

   需求:将明细中的bianry文件全部转化为附件存储,示例代码如下:

def binary_to_attachments(self):
    documemnts = self.env['related.documents'].search([('assmenbly_id', '=',         
                                                       self.assembly_id.id)])
    files = []
    for doc in documents:
        attachment = self.env['ir.attacnment'].create({'datas': doc.file, 'name': 
                                                        doc.filename})
        files.appned((4, attachment.id))
    self.attachment_ids = files
     

9. search_read函数

       search_read函数是再打开tree、看板视图时自动触发的函数,可以重写该方法,以控制要显示的记录,示例代码如下:

@api.model
def search_read(self, domian=None, fields=None, offset=0, limit=80, order=None):
    sql = ''' select row_number() over() as id,
                     model_name,
                     user_id,
                     count(*) as wait_approval_count,
                     string_agg(res_id || '', ',') as res_ids,
                     state     
              from wait_approval wher user_id = %s and state = '%s'
              group by model_name, user_id, state''' %(self.env.user.id, state)
   self.env.cr.excute(sql)
   records = self.env.cr.fetchall()
   vals = []
   for r in records:
       vals.append({'model_name': r[1], 'user_id': r[2]})
   res.create(vals)
   domain = [('id', 'in', res.ids)]
   return super(XdSearchExample, self).search_read(domain=domain, fields=fields, 
                                                   offset=offset, limit=limit,
                                                   order=order)

10. 邮件通知

        odoo框架自带的邮件通知模块mail.message ,示例代码如下:

def mail_message_example(self):
    ...
    user_id = self.env['res.users'].search([('name', '=', 'xxx')], limit=1)
    self.env['mail.message'].create({
        'subject': '通知:xxx',
        'model': xxx,
        'res_id': self.id,
        'record_name': xxx,
        'body': u'有单据%s需要您审批' % sheet_name,
        'partner_ids': [(6, 0, usre_id.partner_id.id)], # 收件人
        'notification_ids': [(5, 0, 0), (0, 0, {'res_partner_id': user_id.partner_id.id,
                            'notification_type': 'inbox'})],
        'subtype_id': self.env['ir.model.data'].xmlid_to_res_id('mail.mt_commet'),
        'message_type': 'notification',
        'author_id': self.env.user.partner_id.id,
        'replay_to': False,
        'email_from': False,
        })
    ...

11. kanban

    kanban写法示例如下:



           
           
           
           
           
           
           
           
           
           
           
           
           
           
           
           
                 
                    

 odoo框架开发汇总_第1张图片

12. 自动生成序列号

  利用ir.sequence模型实现,示例代码如下:

...
  name = fields.Char(string='单号', default='New')
...
@api.model
def create(self, vals):
    if vals.get('name', 'New') == 'New':
       vals['name'] = self.env['ir.sequence'].next_by_code('customer.complaint.sheet') or 
                      '/'
    return super(XdSequenceExapmle, self).create(vals)

     xxx
     customer.complaint.sheet
     CCS%(year)s%(month)s%(day)s
     3
     

13. 计算字段可搜索 

      通常情况下,计算字段如果不存储在数据库中,是无法搜索的,但是可以指定字段的search属性,实现可搜索,示例代码如下;

...
saleman = fields.Many2one('res.users', compute='xxx', string='业务员', 
                          search='_search_saleman_example)
...
def xxx(self):
   todo
...
def _search_saleman_example(self, operator, value):
    ids = []
    mrps = self.env['mrp'].search([])
    users = self.env['res.users'].search([('name', '=', value)]
    for r in mrps:
       if r.saleman.id in users.ids:
            ids.append(r.id)
    if ids:
       return [('id', 'in', tuple(ids))]
    return [('id', '=', '0')]
    

14.线程与线程池 

在导入导出大批量数据时,使用多线程模型,会明显加快速度,使用示例代码如下:

线程:

...
max_connections = 10
pool_sema = threading.BoundedSemaphore(max_connections)
for i in range(4):
    pool_sema.acquire()
    thread = threading.Thread(target=self.supplier_process, args=(arg1, arg2...))
    thread.daemon = True
    thread.start()
    thread.join()
...
def supplier_process(self,args,**kwargs):
    pass

线程池:

...
max_connections = 10
pool_sema = threading.BoundedSemaphore(max_connections)
with ThreadPoolExecutor(max_workers=5) as pool:
    for i in range(4):
        pool_sema.acquire()
        thread = pool.submit(self.supplier_process, (pool_sema ,b), kwargs={'id': 1})
        result = thread.result()
...
def supplier_process(self, *args, **kwargs):
    ...
    pool_sema = arg[0][0]
    ...
    pool_sema.release()

15.Html链接 

可以做一个订单的外部链接,示例代码如下:

...
order_link = fields.Html(string='订单链接')
...
@api.onchange('xxx)
def _compute_order_link(self):
    self.ensure_one()
    href = '/mail/view?model=%s&res_id=%s' %('sale.order', rec.order_id.id)
    rec.order_link = '%s' %(href, rec.order_id.name)
       

16. 接口设计

odoo可以提供对外的接口,以实现与其它系统的互联互通,示例代码如下:

class Main(http.Controller):
     @http.route('/xunde_bids/update/', type='json', methods=['POST'], auth="none", 
                 csrf=False)
     def update_bids(self, db=None, **post):
         if not db and request.session.db and http.db_filter([request.session.db]):
            db = request.session.db
         if not db:
            db = db_monodb(request.httprequest)
         if not db:
            raise exceptions.UserError(_('d参数不能为空'))
         request.session.db = db
         result = False
         with registry(db).cursor() as cr:
              env = Environment(cr, SUPERUSER_ID, {})
              payload = json.loads(request.httprequest.data) or {}
              type = payload.get('type', [])
              if type:
                 raise exceptions.ValidationError(_('api失效!'))
              data = payload.get('data', [])
              result = env['purchase.requisition.line']._update_data(data)
        return {'success': result}  # result为True or False

    

你可能感兴趣的:(python)