当前位置:首页>python>中篇Python(ODOO)篇 第三章 ODOO项目开发(三)添加基础部分模块 1.车辆类型

中篇Python(ODOO)篇 第三章 ODOO项目开发(三)添加基础部分模块 1.车辆类型

  • 2026-09-02 19:06:56
中篇Python(ODOO)篇 第三章 ODOO项目开发(三)添加基础部分模块 1.车辆类型

1.车辆类型

基于从易到难方式,我们先添加车辆类型子模块。
从原始档案我们可以看到车辆类型子模块,有以下几个字段,然后我们开始一步一步添加车辆类型子模块。

字段名

类型

说明

类型编号

字符型

新增字段

车辆类型

字符型

首保公里数

整型

日常保养公里数(每次)

整型

备注

文本型

新增字段,个人习惯

类型编号:ODOO中在设计表的时候,每个表都有name这个字段,ODOO会使用name字段作为记录的标题。在其他模型中调用的时候也会被引用。
一个子模块,一般情况下我们需要创建数据模型、设置访问权限、创建视图层三步。如果有特殊需求还要添加业务逻辑层。

新增数据模型

在左侧列表myaddons->peijia->models上点击鼠标右键,选择new->Python File。
在弹出的对话框输入文件名car_type,点击Python file,PyCharm在指定的目录自动生成文件并打开。
我们录入以下代码:
# -*- coding: utf-8 -*-# &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&# NebulaERP odoo14.0# QQ:50282# 邮件:50282@qq.com# 手机:1111111111# 作者:'Nebula'# 公司网址: www.erpSoft.org# Copyright 2012-2020 Nebula# 日期:2020/3/25# &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&from odoo import fields, modelsclass NebulaCarType(models.Model):    _name = "nebula.car.type"    _description = "车辆类型"    _order = 'name'    name = fields.Char(string='类型编号', size=2, required=True, copy=False, index=True)    name_type = fields.Char(string='类型名称')    active = fields.Boolean(default=True, string='是否启用', size=2)    first_maintain = fields.Integer(string='首保公里数', size=8, default=3500)    every_maintain = fields.Integer(string='日常保养公里数', size=8, default=7500)    note = fields.Text('备注')    # 数据库层面的约束,所以效率比较高    _sql_constraints = [('check_uniq_name', 'unique(name)', '不允许同类型编号'),                        ('check_uniq_type', 'unique(name_type)', '不允许同类型编号')                        ]
解释如下,后续将忽略已经解释过的内容。

# -*- coding: utf-8 -*-在第一行声明编码是utf-8。

用“#&&&&&&&&&&&&&”包裹部分是版权相关信息,读者可自行处理。
from odoo import fields, models:Python代码导入语句,从Odoo包中导入 fields, models模块。我们如果对fields等有兴趣的话,可以按住ctrl键,再用鼠标点击fields,PyCharm就会打开对应的模块文件,使用者可以阅读源码,这就是开源的魅力。
接下来空两行的原因是因为PyCharm默认会用PEP8编码规范检查使用者编写的代码,如果只空一行的话,提示需要2个空行,发现1行。
为了代码美观大方,可读性强,我们尽量遵从PEP8编码规范来编写代码。
class NebulaCarType(models.Model):定义一个类,为了不和其他开发者或者官方类重名,建议采用项目名做前缀,也有开发者缩写做前缀的,或者公司有命名规范的,可依实际情况使用命名方法。这里类名采取驼峰命名法,该类继承自models.Model,或者说这个类是models.Model派生出来的一个子类。
_name = "nebula.car.type":_name属性定义了ODOO全局对该模型引用的标识符。ODOO引用模型的时候用的是_name属性,而不是类名。这里命名方式是用“.”来分隔,一般来说,用该模型业务相关的单数形式+ . + 英文单词来命名,比如系统中的pay.payment就是支付业务的支付模型的意思。笔者因car同名可能性太高,故在前面追加nebula英文名,同样也是个人喜好或看公司规定了。
_description = "车辆类型":_description属性不是必须的,但是为模型提供了一个用户友好的名称,后面可以看到,在设计视图的时候,ODOO会自动提取该字段显示。
_order = 'name':设置浏览模型记录时或列表视图的默认排序。这个值是SQL语句中order by 使用的字符串,所以可以传入符合SQL语法的任意值。
name = fields.Char(string='类型编号', size=2, required=True, copy=False, index=True)
声明一个字段,该字段相关属性如下:
名字:name
字段类型:Char
其他相关属性
size:Char专用属性,设置最大允许尺寸
required: 必填字段
copy:复制记录的时候不复制该字段
index: 索引
defalut:默认值
string: 该字段显示文本
注:结构化查询语言(Structured Query Language)简称SQL,结构化查询语言是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;sql 语句就是对数据库进行操作的一种语言。
active字段用于激活记录,默认active= True的记录才显示。有时候我们想隐藏某些记录的话,需要将active设置为False。
_sql_constraints = [('check_uniq_name', 'unique(name)', '不允许同类型编号')]
类似这个语法是一种约束方式,_sql_constraints是odoo的属性,是一个元组的列表,每个元组是一个数据库约束。元组的第一个元素是约束名字,第二个元素是约束规则(数据库postqresql 约束规则),第三个参数是如果违反约束弹出来的警告信息。
在models目录下的__init__.py文件中引入car_type文件。

设置访问权限

权限通过security/ir.model.access.csv文件来实现,如果没有请自行添加该文件。

内容如下:

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlinkaccess_nebula_car_type,nebula.car.type,model_nebula_car_type,group_peijia_manager,1,1,1,1
id:access_nebula_car_type是记录的外部标识符,模块唯一
name:nebula.car.type描述性标题,默认规则是模块名.类名
model_id:模型的外部标识符,ODOO自动生成的,一般是model_模块名称,点用_代替,
例:model_nebula_car_type
group_id:指明授权的安全组,这里给group_peijia_manager组授权。
perm_write,perm_create,perm_unlink:模块读、写、创建、删除权限。

这里就是给peijia管理组全部权限,赋值1即有权限。在之前添加权限组的时候已经把管理员添加到peijia管理组里面,所以我们用管理员登录是可以使用该模块的。

我们需要检查这个文件是否在__manifest__.py中data段被引用,没有则添加。

我们在'security/groups.xml',下添加一行记录并保存:
'security/ir.model.access.csv',

请注意顺序,ir.model.access.csv调用了groups.xml定义的权限组名,基于先声明再使用的原则,所以顺序不能错。

创建视图层

视图层为用户界面的描述,用XML文件定义,ODOO自动生成界面和交互操作功能。我们一般将视图层存放在views/目录下。

创建表单视图

在views目录新建car_type_views.xml文件,内容如下:
<?xml version="1.0" encoding="utf-8"?><odoo>        <!-- 车辆类型列表 -->    <act_windowid="peijia.action_car_type_views"name="车辆类型"    res_model="nebula.car.type" view_mode="tree,form" /></odoo>
这里可以看到act_windows id的值和添加菜单项action的值相同。这里odoo会自动按照默认视图模版显示。
在__manifest__.py文件中,data段的views/car_views.xml前面添加
‘views/car_type_views.xml',引入视图文件。

添加菜单项

我们在car_views.xml中继续为车辆类型添加菜单,在原顶级菜单下,添加二级菜单:
<menuitem id="menu_peijia_base_data" name="基础资料" sequence="70" parent="menu_peijia_root"/>
在二级菜单下,再添加车辆类型菜单入口:
<menuitem id="menu_car_type_views" name="车辆类型"          parent="menu_peijia_base_data" sequence="110"          action="peijia.action_car_type_views"/>
menuitem:该项是菜单项。
id:是记录的外部标识符,菜单唯一值,方便其他菜单引用。
name:菜单显示的文本
sequence:菜单顺序,ODOO会先按菜单级次再按sequence值从小到大排序
parent:上级菜单的ID
action:会调用该子模块表单视图中ID为指定值的视图。

查看效果

应用中找到陪驾模块,点击升级。
升级完成后,点击左上角图标,点击汽车陪驾,进入汽车陪驾模块。
因目前只有汽车类型模块,且之前已经设置管理员有该模块的权限,所以ODOO会直接进入该模块。
我们点击创建按钮,在默认的录入界面输入第一个车辆类型。
点击保存后,显示单条记录,我们可以点击编辑按钮编辑该条记录,或点击创建按钮创建新的车辆类型,也可以点击动作菜单展开更多操作。
存档:设置字段active为是,反之为取消存档,设置字段active为否,我们之前已经设置active在汽车类型中作为“是否启用”标识,所以存档操作影响是否启用字段值。
删除:删除该条记录。
复制:以当前记录为模版,复制出一条新的记录。
关于复制:复制的时候,会以当前记录为蓝本,后台新建一条记录,再检查这条记录是不是符合条件,符合条件,就保存到数据库中,否则会提示错误信息。
该子模块name字段设置为不可复制,且必填,所以提示name在复制的时候不能完成。
解决方法可以设置一个默认值,每次复制后记得修改该默认值。
当我们新建的时候,如果类型编号或类型名称和数据库中记录重复的时候,也会提示错误。
修改后数据模型中NebulaCarType如下:
class NebulaCarType(models.Model):    _name = "nebula.car.type"    _description = "车辆类型"    _order = 'name'    name = fields.Char(string='类型编号', size=2, required=True,                        copy=False, index=True, default='99')    name_type = fields.Char(string='类型名称', required=True,                             copy=False, default='待修改')    active = fields.Boolean(default=True, string='是否启用', size=2)    first_maintain = fields.Integer(string='首保公里数', size=8, default=3500)    every_maintain = fields.Integer(string='日常保养公里数', size=8, default=7500)    note = fields.Text('备注')    # 数据库层面的约束,所以效率比较高    _sql_constraints = [('check_uniq_name', 'unique(name)', '不允许同类型编号'),                        ('check_uniq_type', 'unique(name_type)', '不允许同类型名称')                        ]

子模块创建小结

    在models目录下新增car_type.py文件,里面有数据模型定义
    在models目录下的__init__.py文件中,添加对car_type文件的引用
    检查项目目录下的__init__.py文件有对models目录的引用
    修改security目录ir.model.access.csv文件,将该数据模型赋权限给陪驾管理组
 检查项目目录下的__manifest__.py文件中data段有对ir.model.access.csv文件的引用
    在views目录下新增car_type_views.xml文件,定义一个最基础的界面
 在项目目录下的__manifest__.py文件中data段添加对car_type_views.xml的引用
    在views目录下car_views.xml文件中新增对车辆类型的相关菜单信息
    重启odoo
    应用中陪驾模块升级
完毕!

完善界面

系统默认的界面可直接拿来使用,但是对于苛刻的用户来说,总是有各种需求,让我们继续完善界面。
视图有多种展现的方式,常用的有以下几个。
    tree:列表视图
    form:表单视图
    graph:图表视图
    search:搜索视图
在xml文件中定义视图的记录,如下代码,代码来源于odoo官方文档。

<record model="ir.ui.view" id="view_id">

<field name="name">view.name</field>

<field name="model">object_name</field>

<field name="priority" eval="16"/>

<field name="arch" type="xml">

<!-- view content: <form>, <tree>, <graph>, ... -->

</field>

</record>

这条记录会转换成ir.ui.view表中的数据,供odoo调用。
<!-- view content: <form>, <tree>, <graph>, ... -->这里可以插入form、tree、graph等视图。
如果遇到更新错误或不生效等问题, 可以在ir_ui_view数据表里删除对应视图记录后再更新。
列表视图代码示例:
有几列就写几列的字段名称。
表单视图示例:
<treestring="Idea list"><fieldname="name"/><fieldname="inventor_id"/></tree>有几列就写几列的字段名称。表单视图示例:<formstring="Idea form"><groupcolspan="4"><groupcolspan="2"col="2"><separatorstring="General stuff"colspan="2"/><fieldname="name"/><fieldname="inventor_id"/>	        </group><groupcolspan="2"col="2"><separatorstring="Dates"colspan="2"/><fieldname="active"/><fieldname="invent_date"readonly="1"/></group><notebookcolspan="4"><pagestring="Description"><fieldname="description"nolabel="1"/></page></notebook><fieldname="state"/></group></form>
每组字段有其特殊含义,读者多看多写自然有所收获。
搜索视图示例:
<search><fieldname="name"/><fieldname="inventor_id"/></search>
如果要添加搜索字段,需要自定义搜索字段。
下面将在car_type_views.xml中段中添加相关代码。

添加表单视图代码

<recordmodel="ir.ui.view"id="peijia.form_car_type_views">    <fieldname="name">peijia.car.type.form</field>    <fieldname="model">nebula.car.type</field>    <fieldname="arch"type="xml">        <formstring="表单">            <sheet>                <divclass="oe_button_box"name="button_box"/>                <groupname="group_top">                    <groupname="group_left">                        <fieldname="name"/>                        <fieldname="active"/>                    </group>                    <groupname="group_right">                        <fieldname="name_type"/>                        <fieldname="first_maintain"/>                        <fieldname="every_maintain"/>                    </group>                    <fieldname="note"widget="many2many_tags"/>                </group>            </sheet>        </form>    </field></record>
效果如下:

添加列表视图代码

<recordmodel="ir.ui.view"id="peijia.tree_car_type_views">    <fieldname="name">peijia.car.type.tree</field>    <fieldname="model">nebula.car.type</field>    <fieldname="priority">1</field>    <fieldname="arch"type="xml">        <treestring="列表">            <fieldname="active"/>            <fieldname="name"/>            <fieldname="name_type"/>        </tree>    </field></record>
效果如下:

添加搜索视图代码

<recordmodel="ir.ui.view"id="peijia.search_car_type_views">    <fieldname="name">peijia.car.type.search</field>    <fieldname="model">nebula.car.type</field>    <fieldname="arch"type="xml">        <search>            <fieldname="name"/>            <fieldname="name_type"/>        </search>    </field></record>
效果如下:
将原代码act_window部分全部删除,用推荐代码替换。
<recordmodel="ir.actions.act_window"id="peijia.action_car_type_views">    <fieldname="name">车辆类型</field>    <fieldname="res_model">nebula.car.type</field>    <fieldname="view_mode">tree,form</field></record>
最后,我们在应用中升级陪驾模块,就可以看到效果了。
代码截图:

关键点

代码中<odoo><data></data></odoo>格式是odoo约定的格式,请勿更改。
<record></record>表示是一条记录。
model的值一般情况下是odoo中的一个特殊的表。
id:不用多说,定义后供外部使用,不可重名。
field:不同的name代表不同的意思,请根据实际情况理解,实在不行先搁置。
widget
Odoo中定义了字段的显示形式,不同字段类型的字段都有其不同的默认widget负责展示。
我们也可以在视图文件上,为具体字段指定具体的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='text' :文本标签
widget="sparkline_bar": 燃尽标签
widget="checkbox" :复选框标签
widget="reference" :关联标签

创建默认数据

留个预习作业,请参考下篇中创建默认数据方法,创建汽车类型的默认数据。
文件名为car_type_data.xml。

最新文章

随机文章