odoo中各字段的含义和用法

视频教程

  • 视频教程地址:http://www.iqiyi.com/playlist514968002.html

  • odoo中字段的定义和含义

# _*_ coding:utf-8 _*_
# author: zhy

import uuid
from itertools import groupby
from datetime import datetime, timedelta
from werkzeug.urls import url_encode
from odoo import api, fields, models, _
from odoo.exceptions import UserError, AccessError
from odoo.osv import expression
from odoo.tools import float_is_zero, float_compare, DEFAULT_SERVER_DATETIME_FORMAT
from odoo.tools.misc import formatLang


class zhy_sale(models.Model):
    _name = "zhy.sale"
    _description = u"销售订单"

    # 隐藏创建人创建日期字段
    _log_access = False

    name = fields.Char(string=u'单据编号', default=lambda self: 'New')
    active = fields.Boolean(default=True, string=u'是否归档', track_visibility='onchange')
    sequence = fields.Integer(string=u'排序', default=10)
    # require=True表示的是必填
    price_unit = fields.Float(string=u'单价', require=True, default=0.0, digits=(10,2))
    note = fields.Text(string=u'备注', track_visibility='onchange')
    content = fields.Html(string=u'正文', strip_style=True)
    # track_visibility='onchange'表示的是会在更改信息的时候,message会提示相关的更改信息
    # 这个要和下面message社交中的应用联合使用
    delivary_date = fields.Date(string=u'发货日期', track_visibility='onchange')
    # default=fields.Datetime.now表示的是获取当前日期
    date_order = fields.Datetime(string=u'单据日期', required=True, readonly=True, index=True, copy=False, default=fields.Datetime.now)
    priority = fields.Selection([
        ('0', '低'),
        ('1', '正常'),
        ('2', '高'),
    ], default='0', index=True, string=u'优先级')
    # res.users表示的是关联的当前用户的表, default表示的是创建的时候默认成当前用户
    # lambda self: self.env.user中user表示的是当前的用户, 如果是想关联其他的用户,可以找个这个用户的id,然后再设置中 default=id即可
    # xml中(ir.actions.act_window)定义{"default_user_id":7}
    user_id = fields.Many2one('res.users', string=u'负责人', index=True, track_visibility='onchange',
                                default=lambda self: self.env.user)
    # 关联字段,一对多的关联 第一个位置表示的是关联的表的名称,第二个字段是表中的字段名称 auto_join表示是否在搜索字段时,生成连接
    order_line = fields.One2many('zhy.sale.line', 'order_id', string=u'订单明细行', copy=True, auto_join=True)
    # 多对多的关系 a_b_rel  a表示的是表名,b表示的是关联字段的表名 a_id b_id可以自己定义 一般是关联表的名称,分别表示的是关联表的名称
    # some_ids = fields.Many2many('models', 'a_b_rel', 'a_id', 'b_id')
    # res.users表和zhy.sale关联的数据放在zhy_sale_res_users_rel中
    users_ids = fields.Many2many('res.users', 'zhy_sale_res_users_rel', 'sale_id', 'user_id', string=u'业务员')

    @api.model
    def _select_objects(self):
        records = self.env['ir.model'].search([])
        return [(record.model, record.name) for record in records] + [('','')]
    # 可以关联所有的字段
    id_object = fields.Reference(string=u'关联', selection='_select_objects')


class zhy_sale_line(models.Model):
    _name = "zhy.sale.line"
    _description = u"销售订单"

    name = fields.Char(string=u'产品名称')
    order_id = fields.Many2one('zhy.sale', string=u'销售订单', require=True, ondelete='cascade', index=True, copy=False)

Python2.7中, string中文前要加u

  • odoo视图定义xml

<odoo>
    
    
    
    <menuitem id="menu_2" name="销售" sequence="12" />
    <menuitem id="menu_2_0" name="CRM" sequence="1" parent="menu_2" />
    <menuitem id="menu_2_1" name="销售" sequence="2" parent="menu_2" />
    <menuitem id="menu_2_99" name="常用报表" sequence="99" parent="menu_2" />
    <menuitem id="menu_2_100" name="设置" sequence="100" parent="menu_2" />

odoo>

  • odoo中基本视图定义(pycharm中快捷键)

<odoo>
    <record id="odoo_form_zhy_sale_views" model="ir.ui.view">
        <field name="name">zhy.sale.formfield>
        <field name="model">zhy.salefield>
        <field name="arch" type="xml">
            <form string="表单">
                <sheet>
                    <div class="oe_button_box" name="button_box">
                    div>
                    <group>
                        <group>
                            <field name="name"/>
                        group>
                        <group>
                        group>
                    group>
                sheet>
            form>
        field>
    record>

    <record id="odoo_tree_zhy_sale_views" model="ir.ui.view" >
        <field name="name">zhy.sale.treefield>
        <field name="model">zhy.salefield>
        <field name="priority">1field>
        <field name="arch" type="xml">
            <tree string="列表">
                <field name="name"/>
            tree>
        field>
    record>

    <record id="odoo_action_zhy_sale_views" model="ir.actions.act_window">
        <field name="name">销售模块field>
        <field name="type">ir.actions.act_windowfield>
        <field name="res_model">zhy.salefield>
        <field name="view_type">formfield>
        <field name="view_mode">tree,formfield>
        <field name="help" type="html">
            <p class="oe_view_nocontent_create">
                Create the first course
            <p>p>
            p>
        field>
    record>
    
    
    <menuitem action="odoo_action_zhy_sale_views" name="zhy_销售" id="menu_zhy_sale_views" sequence="0" />

odoo>

  • 添加字段之后的xml文件解析

<odoo>
    <record id="odoo_form_zhy_sale_views" model="ir.ui.view">
        <field name="name">zhy.sale.formfield>
        <field name="model">zhy.salefield>
        <field name="arch" type="xml">
            <form string="表单">
                <sheet>
                    <div class="oe_button_box" name="button_box">
                    div>
                    
                    <group>
                        <group>
                            <field name="name"/>
                            
                            
                            
                            <field name="price_unit" string="金额" attrs='{"invisible": [("active", "=", True)]}'/>
                            
                            <field name="users_ids" widget="many2many_tags"/>
                        group>
                        <group>
                            <field name="date_order"/>
                            
                            <field name="delivary_date"/>
                            <field name="priority"/>
                            
                            <field name="user_id"/>
                            
                            <field name="id_object"/>
                            
                            <field name="active"/>
                            
                            
                            
                            <field name="sequence" attrs='{"invisible": [("active", "=", True)]}'/>
                        group>
                        
                        <notebook colspan="4">
                            <page string="明细" autofocus="autofocus">
                                
                                <field name="order_line"/>
                                
                                <field name="note"/>
                            page>
                            <page string="正文">
                                <field name="content"/>
                            page>
                        notebook>
                    group>
                sheet>
            form>
        field>
    record>

    <record id="odoo_tree_zhy_sale_views" model="ir.ui.view" >
        <field name="name">zhy.sale.treefield>
        <field name="model">zhy.salefield>
        <field name="priority">1field>
        <field name="arch" type="xml">
            <tree string="列表">
                <field name="name"/>
            tree>
        field>
    record>

    <record id="odoo_action_zhy_sale_views" model="ir.actions.act_window">
        <field name="name">销售模块field>
        <field name="type">ir.actions.act_windowfield>
        <field name="res_model">zhy.salefield>
        <field name="view_type">formfield>
        <field name="view_mode">tree,formfield>
        <field name="help" type="html">
            <p class="oe_view_nocontent_create">
                Create the first course
            <p>p>
            p>
        field>
    record>

    <menuitem action="odoo_action_zhy_sale_views" name="zhy_销售" id="menu_zhy_sale_views" sequence="0" />

odoo>


  • 实际的项目中xml文件各字段的解析


<odoo>
    <data>
         
        
        <record model="ir.ui.view" id="course_form_view">
            <field name="name">course.formfield>                      
            <field name="model">openacademy.coursefield>              
            <field name="arch" type="xml">                               
                <form string="Course Form">                             
                    <sheet>
                        <group>                                          
                            <field name="name"/>                        
                            <field name="responsible_id"/>
                        group>
                         
                        <notebook>
                            <page string="描述">
                                <field name="description"/>
                            page>
                            <page string="授课">
                                <field name="session_ids">
                                    <tree string="授课注册">
                                        <field name="name"/>
                                        <field name="instructor_id"/>
                                    tree>
                                field>
                            page>
                            <page string="关于">
                                这是一个关于notebook的案例
                            page>
                        notebook>
                    sheet>
                form>
            field>
        record>

        <record model="ir.ui.view" id="course_search_view">
            <field name="name">course.searchfield>
            <field name="model">openacademy.coursefield>
            <field name="arch" type="xml">
                <search>
                    <field name="name"/>
                    <field name="description"/>
                search>
            field>
        record>

        
        <record model="ir.ui.view" id="course_tree_view">
            <field name="name">course.treefield>
            <field name="model">openacademy.coursefield>
            <field name="arch" type="xml">
                <tree string="课程详情">
                    <field name="name"/>
                    
                    <field name="responsible_id"/>
                tree>
            field>
        record>

        
        
        
        <record model="ir.actions.act_window" id="course_list_action">
            <field name="name">Coursesfield>               
            <field name="res_model">openacademy.coursefield>  
            <field name="view_type">formfield>
            <field name="view_mode">tree,formfield>
            <field name="context" eval="{'search_default_my_courses': 1}"/>
            <field name="help" type="html">
                <p class="oe_view_nocontent_create">Create the first course
                p>
            field>
        record>

              
        <menuitem id="main_openacademy_menu" name="公开教程"/>
        
        <menuitem id="openacademy_menu" name="公开教程"
                  parent="main_openacademy_menu"/>      
        
        <menuitem id="courses_menu" name="课程" parent="openacademy_menu"
                  action="course_list_action"/>
        
        
         
        

        
        <record model="ir.ui.view" id="session_form_view">
            <field name="name">session.formfield>
            <field name="model">openacademy.sessionfield>
            <field name="arch" type="xml">
                <form string="Session Form">
                    <sheet>
                        <group>
                            <group string="综合的">
                                <field name="course_id"/>
                                <field name="name"/>
                                <field name="instructor_id"/>
                                <field name="active"/>
                            group>
                            <group string="时间表">
                                <field name="start_date"/>
                                <field name="duration"/>
                                <field name="seats"/>
                                <field name="taken_seats" widget="progressbar"/>
                            group>
                        group>
                        <label for="attendee_ids"/>
                        <field name="attendee_ids"/>
                    sheet>
                form>
            field>
        record>

        
        <record model="ir.ui.view" id="session_tree_view">
            <field name="name">session.treefield>
            <field name="model">openacademy.sessionfield>
            <field name="arch" type="xml">
                <tree string="Session Tree" >
                    <field name="name"/>
                    <field name="course_id"/>
                    <field name="taken_seats" widget="progressbar"/>
                tree>
            field>
        record>

        <record model="ir.actions.act_window" id="session_list_action">
            <field name="name">Sessionsfield>
            <field name="res_model">openacademy.sessionfield>
            <field name="view_type">formfield>
            <field name="view_mode">tree,formfield>
        record>

        
        <menuitem id="session_menu" name="授课"
                  parent="openacademy_menu"
                  action="session_list_action"/>    

    data>
odoo>


表单sequence

  • 作用:生成一个带时间的单据编号
  • 用法
    • 创建一个新的data文件夹, 文件夹中创建一个新的xml文件

<odoo>
    <record id="seq_zhy_sale_sequence" model="ir.sequence">
        <field name="name">zhy.salefield>
        <field name="code">zhy.salefield>
        <field name="prefix">A%(year)s%(month)s%(day)sfield>
        <field name="padding">5field>
        <field name="company_id" eval="False" />
    record>
    
odoo>

# 从 ir.squence中取出self._name字段,然后给他生成一个编号
name = fields.Char(string=u'单据编号', default=lambda self: self.env['ir.sequence'].next_by_code(self._name) or 'New')

  • 一般这个单据编号是用在name,char字段中的.

表单日期

from datetime import datetime, timedelta
from odoo.tools import float_is_zero, float_compare, DEFAULT_SERVER_DATETIME_FORMAT

# 获取当前日期
default=fields.Datetime.now
date_order = fields.Datetime(string=u'单据日期', readonly=True, index=True, copy=False, default=fields.Datetime.now)

# 在当前日期上加上多少天(一般是单据日期和发货日期)
# days中的值可以是正值(向前加多少天),也可以是负值(向后减多少天)
default=lambda self: datetime.strptime(fields.Datetime.now(), DEFAULT_SERVER_DATETIME_FORMAT) + timedelta(days=1)

widget="float_time"表示的是可以输入一个时间

hours = fields.Float(string=u’单价’, default=0.0, digits=(10, 2), readonly=False)


domain字段过滤

# 过滤字段, 可以让用户只能选择当前的用户
<field name="user_id" domain="[('id', '=', 1)]"/>

domain="[('id', '=', 1)]"


表单button

  • 在xml中添加

<header>
    <button name="button_loading_draft" states="处理中" string="重置草稿" type="object" class="highlight" />
    <button name="button_done_draft" states="已审核" string="重置草稿" type="object" class="highlight" />
    <button name="button_loading" states="草稿" string="提交草稿" type="object" class="highlight" />
    <button name="button_done" states="处理中" string="审核" type="object" class="highlight" />

    <field name='state' widget='statusbar' statusbar_visible='草稿,处理中,已审核' />
header>

    state = fields.Selection([
            (u'草稿', u'草稿'),
            (u'处理中', u'处理中'),
            (u'已审核', u'已审核'),
        ], string='单据状态', readonly=True, copy=False, default=u'草稿', track_visibility='onchange')

    @api.multi
    def button_loading_draft(self):
        return self.write({'state': u'草稿'})

    @api.multi
    def button_done_draft(self):
        return self.write({'state': u'草稿'})

    @api.multi
    def button_loading(self):
        return self.write({'state': u'处理中'})

    @api.multi
    def button_done(self):
        return self.write({'state': u'已审核'})

    @api.multi
    def action_done(self):
        return self.write({'state': u'取消'})

注意: xml文件中button的name值要和.py文件中函数的名称相对应;

几种状态的对应,可以在视图是观察字段所对应的后端值来定


state 关联字段的只读状态




<record id="odoo_form_zhy_sale_views" model="ir.ui.view">
    <field name="name">zhy.sale.formfield>
    <field name="model">zhy.salefield>
    <field name="arch" type="xml">
        <form string="表单">
            <header>
                <button name="button_loading_draft" states="处理中" string="重置草稿" type="object" class="highlight" />
                <button name="button_done_draft" states="已审核" string="重置草稿" type="object" class="highlight" />
                <button name="button_loading" states="草稿" string="提交草稿" type="object" class="highlight" />
                <button name="button_done" states="处理中" string="审核" type="object" class="highlight" />

                <field name='state' widget='statusbar' statusbar_visible='草稿,处理中,已审核' />
            header>
            <sheet>
                <div class="oe_button_box" name="button_box">
                div>
                <group>
                    <group>
                        <field name="name"/>
                        <field name="price_unit" string="金额" attrs="{'readonly': [('state', 'in', (u'处理中', u'已审核'))]}" />
                        <field name="users_ids" widget="many2many_tags" />
                    group>
                    <group>
                        <field name="date_order"/>
                        <field name="delivary_date"/>
                        <field name="priority"/>
                        <field name="hours" widget="float_time"/>
                        <field name="user_id" />
                        <field name="id_object" />
                        <field name="active"/>
                        <field name="sequence" attrs='{"invisible": [("active", "=", True)]}'/>
                    group>
                    <notebook colspan="4">
                        <page string="明细" autofocus="autofocus">
                            <field name="order_line"/>
                            <field name="note" widget="html"/>
                        page>
                        <page string="正文">
                            <field name="content"/>
                        page>
                    notebook>
                group>
            sheet>
        form>
    field>
record>

# 后端中添加只读状态
# 要结合后端中的state这个字段来进行设置的
price_unit = fields.Float(string=u'单价', default=0.0, digits=(10, 2),
    readonly=True, states={u'草稿': [('readonly', False)], u'处理中': [('readonly', False)]})

state = fields.Selection([
    (u'草稿', u'草稿'),
    (u'处理中', u'处理中'),
    (u'已审核', u'已审核'),
], string='单据状态', readonly=True, copy=False, default=u'草稿', track_visibility='onchange')

一般的情况下, xml的优先级都要高于.py文件中的优先级


权限管理security

  • 在目录下创建一个新的文件夹和文件security/security.xml




<odoo>
    <data>
        <record id="sale_groups" model="ir.module.category">
            <field name="name">销售zfield>
        record>
        <record id="sale_users" model="res.groups">
            <field name="name">销售z-用户field>
            <field name="category_id" ref="sale_groups" />
            <field name="users" eval="[(4, ref('base.user_root'))]" />
        record>
        <record id="sale_manager" model="res.groups">
            <field name="name">销售z-经理field>
            <field name="category_id" ref="sale_groups" />
            <field name="implied_ids" eval="[(4, ref('sale_users'))]" />
            <field name="users" eval="[(4, ref('base.user_root'))]" />
        record>
    data>
odoo>

  • 在实际的项目中怎么设置权限
  • 参考教程:http://www.iqiyi.com/w_19s137nyvt.html?list=19rrmefxri



<header>
    <button name="button_loading_draft" states="处理中" string="重置草稿" type="object" class="highlight" groups="aa_zhy.sale_users" />
    <button name="button_done_draft" states="已审核" string="重置草稿" type="object" class="highlight" groups="aa_zhy.sale_manager" />
    <button name="button_loading" states="草稿" string="提交草稿" type="object" class="highlight" groups="aa_zhy.sale_users" />
    <button name="button_done" states="处理中" string="审核" type="object" class="highlight" groups="aa_zhy.sale_manager"/>

    <field name='state' widget='statusbar' statusbar_visible='草稿,处理中,已审核' />
header>

在实际的项目中, 我们给用户设置了提交审核的权限之后,我们可以用另外的一个用户登录
去查看我们创建的模块,新创建的用户中,我们是没有办法看到我们创建的模块的,这个时候我们需要在管理员账户的设置群组中,找到我们谁知的权限管理模块, 然后进去,给我们的用户设置模块的访问权限即可.

  • 给某些字段设置权限
<!--设置权限组, aa_zhy表示的是文件夹的名称, sale_manager表示的是security.xml文件中设置的权限-->
<!--groups='aa_zhy.sale_manager'-->
price_unit = fields.Float(string=u'单价', default=0.0, digits=(10, 2), readonly=True, groups='aa_zhy.sale_manager')

同样,也可以把groups='aa_zhy.sale_manager'放到xml中也是可以的.

设置完成之后, 就可以用另外的一个账户登录,这个时候,就会发现, 不是管理员用户,就不能查看金额字段了。


表单message的使用

  • 主要是在社交方面的使用
  • 使用中我们会用到系统的mail模块,所以要先把mail模块集成到我们的depends继承中.

_inherit = ['mail.thread']

<div class="oe_chatter">
    <field name="message_follower_ids" widget="mail_followers" />
    <field name="message_ids" widget="mail_thread" />
div>

  • track_visibility='onchange' 这个是结合message使用的, 是把更改的一些信息显示到下面的message中.
  • track_visibility='always' 用户不更改信息的是时候,message也会记录下这些信息.
<!--批量关注的两种方法-->
<!--users_ids是后端定义的多对多的关联字段; 8表示的是当前的这个用户的id-->
self.message_subscribe_user(users_ids=(self.user_id.id))
self.message_subscribe(partner_ids=[8])

<!--批量取消的两种方法-->
self.message_unsubscribe_user(users_ids=(self.user_id.id))
self.message_unsubscribe(partner_ids=[8])


表单onchange的使用

  • 省市区的三级联动
<!--主要是一个many2one字段-->
class res_city1(models.Model):
    _name = "res.city1"
    _description = u"省"

    name = fields.Char(string=u'省')

class res_city2(models.Model):
    _name = "res.city2"
    _description = u"市"

    name = fields.Char(string=u'市')
    city1_id = fields.Many2one('res.city1', string=u'明细', )

class res_city3(models.Model):
    _name = "res.city3"
    _description = u"区"

    name = fields.Char(string=u'区')
    city2_id = fields.Many2one('res.city2', string=u'明细', )

  • 省市区三级联动中提取字段
class zhy_sale_line(models.Model):
    _name = "zhy.sale.line"
    _description = u"销售订单"

    name = fields.Char(string=u'产品名称')
    order_id = fields.Many2one('zhy.sale', string=u'销售订单', require=True, ondelete='cascade', index=True, copy=False)
    
    # 这个地方是定义三个多对一的id字段, 关联对应的表单,提取内容
    city1_id = fields.Many2one('res.city1', string=u'省')
    city2_id = fields.Many2one('res.city2', string=u'市')
    city3_id = fields.Many2one('res.city3', string=u'区')
    
    # onchang时间, 通过第三级(或则是最下级)一级一级向上查询
    @api.onchange('city3_id')
    def onchange_city3_id(self):
        values = {}
        if self.city3_id:
            # city2_id(市)表示的是通过三级的id,找到二级的id.(反向查找)
            values['city2_id'] = self.city3_id.city2_id.id
            # city1_id(省)表示的是通过三级区的id,找到二级市的id,再找到一级省的id.(反向查找)
            values['city1_id'] = self.city3_id.city2_id.city1_id.id
        self.update(values)


class res_city1(models.Model):
    _name = "res.city1"
    _description = u"省"

    name = fields.Char(string=u'省')


class res_city2(models.Model):
    _name = "res.city2"
    _description = u"市"

    name = fields.Char(string=u'市')
    city1_id = fields.Many2one('res.city1', string=u'明细', )


class res_city3(models.Model):
    _name = "res.city3"
    _description = u"区"

    name = fields.Char(string=u'区')
    city2_id = fields.Many2one('res.city2', string=u'明细', )

  • xml中视图展示

<notebook colspan="4">
    <page string="明细" autofocus="autofocus">
        <field name="order_line">
            
            <tree string="列表" editable="bottom">
                <field name="city1_id" />
                
                
                
                <field name="city2_id" domain="[('city1_id', '=', city1_id)]" />
                <field name="city3_id" domain="[('city2_id', '=', city2_id)]" />
            tree>
        field>
        <field name="note" widget="html"/>
    page>
    <page string="正文">
        <field name="content"/>
    page>
notebook>

表单中数量和金额的合计

# 新增数量,单价,和小计等字段.这些字段都是要float类型
# depends中依赖的是自己心定义的两个字段,如果这两个字段发生变化,则执行这个函数
@api.depends('product_uom_qty', 'price_unit')
def _compute_amout(self):
    for order in self:
        order.price_subtotal = order.product_uom_qty * order.price_unit

product_uom_qty = fields.Float(string=u'数量', required=True, default=1.0)
price_unit = fields.Float(string=u'单价', required=True, default=0.0, digits=(10, 2))
# compute是关联一个函数.我们在这个函数中可以写计算逻辑
price_subtotal = fields.Float(compute='_compute_amout', string=u'小计')


# 在其他的表中做关联和金额合计的时候
# 这个表中依赖的是外键表中的一个字段;通过外键表找到这个字段,然后对这个字段进行操作
@api.depends('order_line.price_subtotal')
def _compute_amount(self):
    for order in self:
        total = sum(line.price_subtotal for line in order.order_line)
        order.amount = total
        
amount = fields.Float(compute='_compute_amount', string=u'小计')
order_line = fields.One2many('zhy.sale.line', 'order_id', string=u'订单明细行', copy=True, auto_join=True)

表单unlink删除重写事件

  • odoo中已经做好了表单的删除功能, 我们只需要继承这个功能就好.
  • 我们做的这个案例中, 只有我们的表单处理草稿状态的时候,我们才能删除这个表单. 当我们的表单处理处理中或者审核状态的时候,我们是不能删除的.
# @api.multi表示的是可以选择多个 重写unlink()方法
# 当界面点击删除事件的时候会触发
@api.multi
def unlink(self):
    for order in self:
        # 判断当前的用户和表单的创建用户是否一致, 如果不一致不允许删除.
        if order.user_id:
            # user_id(字段名称)
            if order.user_id.id != self._uid:
                raise UserError(u'只能删除自己的单据')
        if order.state != u"草稿":
            raise UserError(u'只能删除草稿单据')
        # self.env['amos.workflow'].sudo.seach([('res_model', '=', self._name), ('res_id', '=', order.id)]).unlink()
        # self.env['if.message'].sudo.seach([('res_model', '=', self._name), ('res_id', '=', order.id)]).unlink()
    # 关联的是哪张表
    return super(zhy_sale, self).unlink
    
# 项目中是实际会用到的
@api.multi
def unlink(self):
    for order in self:
        if order.user_id:
            if order.user_id.id != self._uid:
                raise UserError(u'只能删除自己的单据aaaa')
        # 这个地方有问题, 当不能删除的时候, 注意下判断条件(可以使用debug),打印出判断条件对比下就可以了. 
        if order.state.encode('utf-8') != "草稿":
            print(order.state, type(order.state))
            raise UserError(u'只能删除草稿单据bbbb')
    return super(zhy_sale, self).unlink()

# 其他的写法
# @api.multi
# def unlink(self):
#     if any(order.state in (u'处理中', u'已审核') for order in self):
#         raise exceptions.UserError(u'只能删除草稿单据啊啊啊啊啊啊.')
#     super(zhy_sale, self).unlink()


表单create创建重写事件

  • 可以创建自己的公司的编号等
  • 可以修改字段的值
# vals表示的是界面传入进来的所有的值
# self._context表示的传入进来的上下文的值   
# 当创建的时候会触发
@api.model
def create(self, vals):
    # print(self._context, u'这是上下文')
    # print(vals, u'这是界面传入进来的值')
    if vals.get('name', 'New') == 'New':
        # 这个地方表示是判断传入进来的值中有没有company_id字段, 如果有的话, 设置一个单据编号
        if 'company_id' in vals:
            # with_context传上下文的 next_by_code下一个字段
            vals['name'] = self.env['ir.sequence'].with_context(force_company=vals['company_id']).next_by_code(self._name) or 'New'
        else:
            vals['name'] = self.env['ir.sequence'].next_by_code(self._name) or 'New'
    # 可以指定修改某个值
    vals['hours'] = 100.00
    line = super(zhy_sale, self).create(vals)
    return line
    

表单widget的使用

  • 参考: https://www.kancloud.cn/hx78/odoo_10/416226
# odoo中常用的widget

widget="statusbar" 头部状态条标签
widget="email" 电子邮件地址标签
widget="selection" 下拉选择标签
widget="mail_followers" 关注者标签
widget="mail_thread" 消息标签
widget="progressbar" 进度条,按百分比标签
widget="one2many_list" 一对多列表标签
widget="many2many_tags" 多对多显示标签
widget="url" 网站链接标签
widget='image' 图片标签
widget="many2many_kanban" 看版标签
widget="handler" 触发标签
widget="radio" 单选标签
widget="char_domain" 字符域标签
widget="monetary" 价格(和精度位数相关)标签
widget="float_time" 单精度时间标签
widget="html" html相关标签
widget="pad" pad显示相关标签
widget="date" 日期标签
widget="monetary" 金额标签
widget='text' 文本标签
widget="sparkline_bar" 燃尽标签
widget="checkbox" 复选框标签
widget="reference" 关联标签

<field name="partner_type" nolabel="1" widget="selection" string="" \
attrs="{'required': [('payment_type', 'in', ('inbound', 'outbound'))], \
'invisible': [('payment_type', 'not in', ('inbound', 'outbound'))], \
'readonly': [('state', '!=', 'draft')]}"/>


表单write修改重写事件(时间的改写)

# 当修改表单中数据 的时候会被触发
@api.multi
def write(self, vals):
    print(vals, u'我是修改之后的值')
    if vals.has_key('price_unit'):
        print(vals.has_key('price_unit'), 1111111)
        if vals['price_unit'] > 100000:
            print(isinstance(vals['price_unit'], str))
            print(vals['price_unit'], type(vals['price_unit']))
            raise UserError(u'警告: 你没有权限修改')
    return super(zhy_sale, self).write(vals)


表单active(归档使用)

  • 当一件事情完结的时候, 点击归档,则这件事情就被隐藏掉了;当我们想再去查看的时候, 在筛选条件中是否归档选择为假即可.

<div class="oe_button_box" name="button_box">
    <button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive">
        <field name="active" widget="boolean_button" options='{"terminology": "archive"}' />
    button>
div>


@api.multi
def toggle_active(self):
    for recode in self:
        print(recode, "我来了")
        recode.active = not recode.active


表单隐藏按钮

隐藏新建,隐藏修改,隐藏删除
create=“false”
edit=“false”
delete=“false”

<form string="表单" create="false" edit="false" delete="false"> 
form>
或者
<form string="表单" create="0" edit="0" delete="0"> 
form>

  • 想让哪部分按钮隐藏, 只需要把相应的代码中的字段设置为false或者0即可.

表单字段related

  • 一般是关联某个字段, 做实时同步等
# 两张变中的字段也是可以关联的
# 表zhy.sale中的字段
delivery_date = fields.Date(string=u'发货日期',track_visibility='onchange',)

# 表zhy.sale.line中的字段
# order_id是关联的其他表
order_id = fields.Many2one('zhy.sale', string=u'销售订单', require=True, ondelete='cascade', index=True, copy=False)
# related="表中外键表的字段" 一定要注意字段的类型Date一定要和关联的其他表的字段类型一致
delivery_date = fields.Date(related='order_id.delivery_date', string=u'发货日期', store=True)


api各个装饰器的区别

  • api.depends:当用到其他字段的时候需要用到depends(实时计算字段)
    • eg:金额的统计的时候, 小计需要关联其他的两个字段
  • api.onchange:实时更新用户界面,当用户在表单中更改某个字段的值时,其他相关字段可以在不需保存的情况下实时更新.
    • eg:城市的三级联动
  • odoo.api.model(method):在记录行方式下装饰一个内容不明确、但模型明确的方法
  • odoo.api.multi(method):在记录行方式下装饰一个对记录进行操作的方法
  • odoo.api.depends(*args):返回为compute方法指定依赖字段的装饰器,每个参数必须是字符串
  • odoo.api.constrains(*args):装饰一个约束检查方法,每个参数必须是需要检查的字段
    • 在检验失败时抛出ValidationError错误,且不支持关联字段检验
  • odoo.api.onchange(*args):返回一个监控指定字段的onchange方法的装饰器,每个参数必须是字段名称
    • 该函数可能会返回以数据字典形式组装的当前更改字段的domain表达式和一个警告消息,不支持关联字段处理

你可能感兴趣的:(odoo)