model
开篇提要:想要在odoo界面显示数据必须具有四部分:
1.模型对象(数据库对象)
2.显示视图(在web界面显示数据)
3.桥梁(web端获取数据)
4.菜单(web端点击显示按钮)
from odoo import models, fields, api
# 建立模型
class hobby(models.Model):
_name = 'test1.hobby'
_description = u'爱好'
name = fields.Char(string=u'爱好')
test1_ids = fields.One2many('test1.test1','hobby_id',string='测试模块') #一对多 第一个参数为对面模型名称,第二个参数为关联的字段
test1_count = fields.Integer(string=u'测试数量',compute="_compute_test1_num")
@api.depends('test1_ids')
@api.multi
def _compute_test1_num(self):
for res in self:
res.test1_count = len(res.test1_ids)
# 建立模型
class test1(models.Model):
_name = 'test1.test1' #定义模型名字(必填项)
_description = u'测试模块' #为模型加注释(可选)
name = fields.Char(string=u'名字') #字符类型
age = fields.Integer(string=u'年龄') #数字类型
sex = fields.Selection(selection=[('man',u'男'),('woman',u'女')],default = 'man') #选择
born = fields.Datetime(string=u'出生日期') #日期类型
expectation_salary = fields.Float(digits=(6,2),string=u'期望薪资') #浮点类型 digits为设置长度与小数点
expectation_work = fields.Char(string=u'期望职位')
is_expired = fields.Boolean(string=u'是否超过18岁',compute="_compute_is_exipred") #布尔类型
my_self = fields.Text(string=u'自我介绍') #文本类型
hobby_id = fields.Many2one("test1.hobby",string=u'爱好',ondelete='set null',domain=[('mame','=','篮球')]) # 多对一 第一个参数为关联的对象模型名字,第二个参数为赋值,第三个参数为关联对象关系,第四个参数为是否建立索引
#fields里面存在的方法
string = '' #重命名(在页面可以被看见的名字)
help = '' #提示信息(在页面指定位置悬停时可以看到的提示信息)
default = '' #默认值(值为空时默认填入)
class = '' #为其添加属性(odoo自带bootstrap)
invisible = True or False #是否不可见
readonly = True or False #是否只读
required = True or False #是否不为空
compute = '方法名' #计算(不计入数据库)
domain= [('','','')] #筛选(第一个参数为字段,第二个为逻辑符号,第三个为判断值)
index = True or False #是否在该字段建立索引
@api.depends('born') # 时时检测,发生改变就触发
@api.multi # self为数据集的时候使用(env包含ids参数)
#api.one # self为单个数据的时候使用,返回为列表
#api.model # self为数据集的时候使用(env不包含ids参数)
#api.onchange('字段名') # 对页面进行操作时触发的字段(可以强制提交)
#api.constrains('字段名') # 对数据库进行操作时触发的方式
def _compute_is_exipred(self): # self指的是模型对象,是有实际意义的!!!!
from dateutil import parser
now_time = fields.Datetime.now()
now_time = parser.parse(now_time)
for res in self:
if res.born:
born_time = parser.parse(res.born)
res.is_expired = (now_time-born_time).days>365*18
else:
raise UserError(_(u'未满18岁')) # 此方法会使前端出现提示信息
注:self有自己的方法!!!!
self.env.cr 数据库游标对象,用于查询数据库
self.env.uid 当用用户数据库id
self.env.user 当前用户的记录
self.env.context 上下文词典
self.env,ref(xml_id) 返回与xml_id对应的记录
self.env[model_name] 返回模型的实例
xml
显示视图
<record model="ir.ui.view" id="hobby_list"> #如果要将值写入要模型中时,model为模型名字,如果要进行数据展示时,model为ir.ui.view #id为外部标识符(调用都用它)
<field name="name">hobby</field> #单纯在页面上展示名字
<field name="description">this is my hobby</field> #单纯在页面上展示提示
<field name="model">test1.hobby</field> #(重要)对应的模型表
<field name="arch" type="xml"> #可以当作展示数据时必带的一项
<form string="Idea form"> #用来编辑和创建的表单
<group colspan="4"> #分组
<group colspan="2" col="2">
<separator string="General stuff" colspan="2"/> #附加标题
<field name="name"/> # 这是上面模型表里的字段
<field name="inventor_id"/> # 这是上面模型表里的字段
</group>
<notebook colspan="4"> #选择框
#多对一这么写
<page string="ceshi"> #选项卡
<field name="test1_ids"> # 多对一关系的字段
<tree create="0" edit="0" delete="0">
<field name="name"/>
<field name="sex"/>
<field name="born"/>
<field name="nation"/>
<field name="expectation_salary"/>
<field name="expectation_work"/>
<field name="is_expired"/>
</tree>
</field>
</page>
#普通字段
<page string="Description"> #选项卡
<field name="description" nolabel="1"/> #字段名
</page>
</notebook>
</group>
<sheet>据我观测,这是一个画布,有多大的数据,就会有多大的画布</sheet>
</form>
#以表格形式显示记录
<tree decoration-{$name}='判断条件'> # $name可以为bf(font-weight: bold),可以为it (font-style: italic),也可以为danger, info, muted, primary, success or warning
<field name='模型中的字段名'/>
</tree>
</field>
</record>
注:对标签的补充与介绍
<tree>标签:用来做最简单的信息展示,通常被用来做可看数据的展示。
decoration-{$name}="条件": 根据条件更改样式,{$name}通常是bf(font-weight: bold),it(font-style: italic)或bootstrap颜色(danger, info,muted,primary,success或warning)
editable = "top" or "buttom" :直接可以在tree视图上编辑
<from>标签:用来做详细的信息展示,通常被用来做所有数据的展示,也是在这里面进行修改和删除
<group>标签:分块,通常被用来做数据的隔开
<notebook>标签:选项卡标识符,有这个才被认为是选项卡
<page>标签:配合<notebook>标签使用定义选项卡与为其赋值
<calendar>标签:以日历形式显示事件
color:标识颜色
date_start:开始时间
date_stop:结束时间
<search>标签:被用来做搜索的标识符
<filter>标签:配合search使用,真正用来进行搜索过滤的标签
domain:搜索条件一般里面有三个参数要填写,具体看下面代码
context:分组条件一般里面有两个参数要填写,具体看下面代码
搜索视图
<record model="ir.ui.view" id="test1_search"> #大部分与显示视图一样就不过多介绍了
<field name="name">test1</field>
<field name="model">test1.test1</field>
<field name="arch" type="xml">
<search string="search_test"> #从这里开始定义搜索视图,这里string没有太多的意义
<field name="name"/> #搜索时会弹出对应类别的信息
<field name="sex"/>
<field name="hobby_id"/>
<field name="is_expired"/>
<separator/> #当作分隔符也可以当作副标签
<!--<filter string="man" name="man" domain="[('sex','=','1')]"/>-->
<!--<filter string="woman" name="woman" domain="[('sex','=','2')]"/>-->
<!--<separator/>-->
# 在筛选中显示,domain为显示条件
<filter srting="more" name="more" domain="[('is_expired', '=', True)]"/>
<filter srting="less" name="less" domain="[('is_expired', '=', False)]"/>
<separator/>
# 在分组中显示,domain为搜索条件,context为分组条件
<group expend="0" string="group">
<filter string="sex" name="sex" domain="[]" context="{'group_by':'sex'}"/>
<filter string="hobby" name="hobby" domain="[]" context="{'group_by':'hobby_id'}"/>
</group>
</search>
</field>
</record>
获取数据
#通过桥梁获取数据
<record model="ir.actions.act_window" id="act_test_windows"> #model中有5种方法
<field name="name">个人信息3</field>
<field name="res_model">test1.test1</field>
<field name="view_mode">tree,form</field>
</record>
菜单
<menuitem id="main_openacademy_menu" name="个人信息"/> #一级菜单
<menuitem id="openacademy_menu" name="详情" parent="main_openacademy_menu"/> #二级菜单
<menuitem id="test_menu" name="test" parent="openacademy_menu" action="act_test_windows" sequence="1" /> #三级菜单通过action关联桥梁
报表(打印)
<!--创建打印对象并在页面添加打印按钮-->
<report
id="test_report" #自定义id
model="test.session" #model模型
string="测试打印" #外部按钮名称
report_type="qweb-pdf" #打印格式为pdf(如果为hrml只需将pdf改成html)
name="test.test_template" #打印内容id
file="test.views" #打印内容位置(file.view)
attachment_use="Ture" #如果设置为True,报表将使用由 attachment 表达式生成的名称作为记录的附件存储;如果需要报表只生成一次(例如法律原因)
/>
例外还有
report_name = "xxx" #pdf的名字
attachment = "" #定义报告名称的Python表达式;该记录可以作为变量 object 访问
<!--创建打印内容-->
<template id="test_template"> #打印内容id
<t t-call="report.html_container"> #打印的位置(默认填写这个就好了)
<t t-foreach="docs" t-as="o"> #t-foreach循环 t-as里是循环出来的值
<t t-call="report.external_layout"> #添加默认的页眉和页脚
<div class="page"> #存放内容开始的标志,里面为html格式
<h2>Report title</h2>
<p>This object's name is <span t-field="o.name"/></p>
</div>
</t>
</t>
</t>
</template>
注:由于这是一个QWeb模板,您可以访问模板接收的 docs 对象的所有字段。
docs #记录当前报表
doc_ids #docs 记录的id列表
doc_model #模型为 docs 记录
time #引用Python标准库的 time
user #res.user 记录用户打印报表
res_company #记录当前 user 的公司