參考资料点击这里.

构建Odoo模块

模块组成

  • 业务对象

    业务对象声明为Python类, 由Odoo自己主动加载.

  • 数据文件

    XML或CSV文件格式, 在当中声明了元数据(视图或工作流)、配置数据(模块參数)、演示数据等.

  • Web控制器

    处理Web浏览器发来的requests.

  • 静态web数据

    Web用到的图像, CSS或JavaScript文件.

模块结构

一个Odoo模块也是一个Python模块, 存放在一个文件夹中, 包括一个__init__.py文件, 用于导入其它Python模块.

from . import mymodule

odoo.py提供了一个子命令scaffold能够方便地创建一个空的模块.

$ odoo.py scaffold <module name> <where to put it>

命令运行后, 将会创建一个子文件夹而且当中包括了Odoo模块所需的一些基本文件.

练习 #1

运行 ./odoo.py scaffold openacademy addons, 在addons文件夹下创建一个名为openacademy的模块, 生成的文件夹文件结构例如以下.

openacademy
├── __init__.py
├── __openerp__.py
├── controllers.py
├── demo.xml
├── models.py
├── security
│   └── ir.model.access.csv
└── templates.xml

各文件内容请查看文件或查看原文, 然后对__openerp__.py中的几种标识文本进行改动.

对象关系映射

ORM层是Odoo的一个关键组件, 它能够避免大部分的SQL语句编写从而提高扩展性和安全性.

业务对象用派生自Model的Python类(模型)来编写, 该类的_name属性定义了模型在Odoo系统中的名称.

from openerp import models
class MinimalModel(models.Model):_name = 'test.model'

字段

字段定义模型能够存储什么以及在哪里存储, 字段在模型类中用属性来定义.

from openerp import models, fieldsclass LessMinimalModel(models.Model):_name = 'test.model2'name = fields.Char()

通用属性

与模型相似, 字段也能够通过參数传递对其进行设定:

name = field.Char(required=True)

字段的经常使用属性有:

  • string (unicode, default: field’s name)

    The label of the field in UI (visible by users).

  • required (bool, default: False)

    If True, the field can not be empty, it must either have a default value or always be given a value when creating a record.

  • help (unicode, default: ‘’)

    Long-form, provides a help tooltip to users in the UI.

  • index (bool, default: False)

    Requests that Odoo create a database index on the column

简单字段

字段能够分为两类: 简单字段和关系字段. 前者为原子值, 直接保存在模型相应的数据库表中; 后者连接到其它的记录上(能够是同样的模型也能够是不同的模型).

Boolean, Date, Char这些都是简单字段.

保留字段

Odoo在模型中自己主动创建并维护一些字段, 这些字段就是保留字段, 这些字段数据不须要也不应该手动去改动.

  • id (Id)

    the unique identifier for a record in its model

  • create_date (Datetime)

    creation date of the record

  • create_uid (Many2one)

    user who created the record

  • write_date (Datetime)

    last modification date of the record

  • write_uid (Many2one)

    user who last modified the record

特殊字段

默认情况下, Odoo要求模型中有一个name字段, 用于显示和搜索, 通过设置_rec_name也能够达到这种目的.

练习 #2

在openacademy模块中定义一个新的模型Course, openacademy/models.py内容例如以下:

# -*- coding: utf-8 -*-
from openerp import models, fields, api
class Course(models.Model):_name = 'openacademy.course'name = fields.Char(string="Title", required=True)description = fields.Text()

数据文件

Odoo是一个高度数据驱动的系统, 尽管使用Python代码来定制模块行为, 但非常多模块数据是在其加载时setup的, 而且有些模块仅仅为Odoo加入数据.

通过数据文件来定义模块数据, 比如能够使用XML文件里的<record>元素定义数据, 每个<record>元素创建或者更新数据库中的一条记录, 形式例如以下:

<openerp><data><record model="{model name}" id="{record identifier}"><field name="{a field name}">{a value}</field></record></data>
<openerp>
  • model

    Odoo模型名.

  • id

    外部ID(External Identifier), 通过它能够引用到记录(而且不须要知道记录所在的数据库ID).

  • 元素

    name属性用于确定字段名称(比如description), 该元素的body给出字段的值.

数据文件必须在模块加载清单文件列表中, 也就是__openerp__.py的’data’列表(所有加载)或’demo’列表(仅仅有设定为加载演示数据才会加载)中.

练习 #3

创建一个数据文件来向Course中加入数据, 编辑openacademy/demo.xml, 并确认__openerp__.py的’demo’列表中有该文件.

<openerp><data><record model="openacademy.course" id="course0"><field name="name">Course 0</field><field name="description">Course 0's descriptionCan have multiple lines</field></record><record model="openacademy.course" id="course1"><field name="name">Course 1</field><!-- no description for this one --></record><record model="openacademy.course" id="course2"><field name="name">Course 2</field><field name="description">Course 2's description</field></record></data>
</openerp>

动作和菜单

在Odoo中, 动作和菜单都是定义在数据库中的数据记录, 一般通过数据文件来定义.

动作能够由三种方式触发:

  • 点击菜单项(菜单项链接到特定动作)
  • 点击视图上的按钮(假设按钮连接到动作)
  • 作为对象的上下文动作

使用<menuitem>声明一个ir.ui.menu并将其连接到一个action, 能够用以下的形式的代码.

<record model="ir.actions.act_window" id="action_list_ideas"><field name="name">Ideas</field><field name="res_model">idea.idea</field><field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_ideas" parent="menu_root" name="Ideas" sequence="10"action="action_list_ideas"/>

注意: action必须先于menu的连接使用定义, 数据文件在加载时顺序地运行, 所以动作的ID必须首先存在于数据库中才干使用.

练习 #4

定义一个新的菜单项訪问OpenAcademy课程.

创建openacademy/views/openacademy.xml文件, 并在当中加入动作和菜单.

<?

xml version="1.0" encoding="UTF-8"?

>

<openerp> <data> <!-- window action --> <!-- The following tag is an action definition for a "window action", that is an action opening a view or a set of views --> <record model="ir.actions.act_window" id="course_list_action"> <field name="name">Courses</field> <field name="res_model">openacademy.course</field> <field name="view_type">form</field> <field name="view_mode">tree,form</field> <field name="help" type="html"> <p class="oe_view_nocontent_create">Create the first course </p> </field> </record> <!-- top level menu: no parent --> <menuitem id="main_openacademy_menu" name="Open Academy"/> <!-- A first level in the left side menu is needed before using action= attribute --> <menuitem id="openacademy_menu" name="Open Academy" parent="main_openacademy_menu"/> <!-- the following menuitem should appear *after* its parent openacademy_menu and *after* its action course_list_action --> <menuitem id="courses_menu" name="Courses" parent="openacademy_menu" action="course_list_action"/> <!-- Full id location: action="openacademy.course_list_action" It is not required when it is the same module --> </data> </openerp>

在__openerp__.py中加入这个数据文件名称到’data’.

'data': [# 'security/ir.model.access.csv','templates.xml','views/openacademy.xml',],

更新模块后能够看到菜单, 操作看看效果.

基本视图

视图定义了模型数据怎样显示, 每种类型的视图代表一种数据可视化模式.

主要的视图定义

一个视图是以一条ir.ui.view模型数据的形式定义的.

<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>

Tree views

Tree view也被称为list views, 在一个表格中显示记录. 根元素是<tree>, 最简形式的tree view仅仅是简单地列出每条记录的多个字段, 每个字段为一列.

<tree string="Idea list"><field name="name"/><field name="inventor_id"/>
</tree>

Form views

Form用于创建或编辑单条记录, 根元素是<form>, 能够在form中组合各种高层结构元素(如groups, notebooks)以及交互元素(如buttons, fields).

<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><group colspan="2" col="2"><separator string="Dates" colspan="2"/><field name="active"/><field name="invent_date" readonly="1"/></group><notebook colspan="4"><page string="Description"><field name="description" nolabel="1"/></page></notebook><field name="state"/></group>
</form>

练习 #5

为openacademy创建form view, views/openacademy.xml数据文件里添加<record model=”ir.ui.view”…>内容.

<?xml version="1.0" encoding="UTF-8"?>
<openerp><data><record model="ir.ui.view" id="course_form_view"><field name="name">course.form</field><field name="model">openacademy.course</field><field name="arch" type="xml"><form string="Course Form"><sheet><group><field name="name"/><field name="description"/></group></sheet></form></field></record><!-- window action --><!--The following tag is an action definition for a "window action",

更新模块, 创建一个Course, 能够看到form view变了.

练习 #6

使用notebook. 在form view中, 将description字段放在一个tab中, 方便随后加入其它tabs, 对练习#5的form view数据做例如以下改动.

        <sheet><group><field name="name"/></group><notebook><page string="Description"><field name="description"/></page><page string="About">This is an example of notebooks</page></notebook></sheet></form>
</field>

更新模块, 看效果.

More

还能够使用HTML为form view提供更加灵活的布局, 比如以下的样例.

<form string="Idea Form"><header><button string="Confirm" type="object" name="action_confirm"states="draft" class="oe_highlight" /><button string="Mark as done" type="object" name="action_done"states="confirmed" class="oe_highlight"/><button string="Reset to draft" type="object" name="action_draft"states="confirmed,done" /><field name="state" widget="statusbar"/></header><sheet><div class="oe_title"><label for="name" class="oe_edit_only" string="Idea Name" /><h1><field name="name" /></h1></div><separator string="General" colspan="2" /><group colspan="2" col="2"><field name="description" placeholder="Idea description..." /></group></sheet>
</form>

Search views

Search views用来自己定义list views及其它统计/多条记录视图中的搜索字段. 根元素为<search>, 其子元素定义了在哪些字段上进行搜索.

<search><field name="name"/><field name="inventor_id"/>
</search>

假设一个模型未定义相应的Search view, odoo自己主动创建一个仅搜索name字段的search view.

练习 #7

加入title以及description搜索, 在views/openacademy.xml中定义search view.

    </field>
</record><record model="ir.ui.view" id="course_search_view"><field name="name">course.search</field><field name="model">openacademy.course</field><field name="arch" type="xml"><search><field name="name"/><field name="description"/></search></field>
</record><!-- window action -->
<!--The following tag is an action definition for a "window action",

更新模块, 搜索框输入字符后能够看到下方能够选择搜索description字段.

模型中的关联

概述

一个模型中的记录可能关联到其它模型的记录, 比如销售订单记录会关联到一个包括客户信息的客户记录.

练习 #8

为了说明数据关联, 首先添加新的模型.

Open Academy模块中, 一个session是一个在特定时间针对特定听众讲授课程的过程. 须要为session创建相应的模型.

session具有name, 開始日期, 持续时间以及座位数量等. 此外还须要加入相应的action和menuitem显示模型数据.

首先在openacademy/models.py中创建Session类.

class Session(models.Model):_name = 'openacademy.session'name = fields.Char(required=True)start_date = fields.Date()duration = fields.Float(digits=(6, 2), help="Duration in days")seats = fields.Integer(string="Number of seats")

然后在openacademy/view/openacademy.xml中加入用于訪问session模型的action和menuitem定义.

        <!-- Full id location:action="openacademy.course_list_action"It is not required when it is the same module --><!-- session form view --><record model="ir.ui.view" id="session_form_view"><field name="name">session.form</field><field name="model">openacademy.session</field><field name="arch" type="xml"><form string="Session Form"><sheet><group><field name="name"/><field name="start_date"/><field name="duration"/><field name="seats"/></group></sheet></form></field></record><record model="ir.actions.act_window" id="session_list_action"><field name="name">Sessions</field><field name="res_model">openacademy.session</field><field name="view_type">form</field><field name="view_mode">tree,form</field></record><menuitem id="session_menu" name="Sessions"parent="openacademy_menu"action="session_list_action"/></data>
</openerp>

digits=(6,2)确定浮点数的精度, 6表示总的数字位数(不包括小数点), 2表示小数点后的位数. 所以, digits=(6,2)小数点前最多4位.

转载于:https://www.cnblogs.com/wzzkaifa/p/7338602.html

[精]Odoo 8.0深入浅出开发教程-模块开发基础相关推荐

  1. 微信小程序网悦新闻开发--视频模块开发(四)

    目录 微信小程序网悦新闻开发--功能介绍(一) 微信小程序网悦新闻开发--小程序配置(二) 微信小程序网悦新闻开发--首页模块开发(三) 微信小程序网悦新闻开发--视频模块开发(四) 微信小程序网悦新 ...

  2. 微信小程序网悦新闻开发--首页模块开发(三)

    目录 微信小程序网悦新闻开发--功能介绍(一) 微信小程序网悦新闻开发--小程序配置(二) 微信小程序网悦新闻开发--首页模块开发(三) 微信小程序网悦新闻开发--视频模块开发(四) 微信小程序网悦新 ...

  3. 视频教程-基于python的微信公众号开发教程-微信开发

    基于python的微信公众号开发教程 微信企业号星级会员.10多年软件从业经历,国家级软件项目负责人,主要从事软件研发.软件企业员工技能培训.已经取得计算机技术与软件资格考试(软考)--"信 ...

  4. Odoo 8.0深入浅出开发教程

    转自:http://blog.sunansheng.com/python/odoo/odoo.html Table of Contents 1. ERP简介 1.1. Odoo历史 1.2. ERPⅡ ...

  5. Luat模块应用手册-指南-luat二次开发教程-功能开发教程-HTTP

    关键词:HTTP,POST,GET 目录 http 简介 API说明 实现流程 示例 执行HTTP请求的回调函数 HTTP请求函数 常见问题 是否支持HTTPS 为什么频繁请求会失败 为什么POST ...

  6. 指南-Luat二次开发教程-功能开发教程-SOCKET

    目录 socket 简介 API说明 实现流程 同步与异步 示例 开机与连接网络 连接服务器 socket发送与接收消息 常见问题 连接服务器失败 最多同时支持多少个连接 socket异常的情况排查 ...

  7. 鸿蒙开发板怎么玩?Neptune开发教程---OpenHarmony开发体验-环境搭建-编译-烧录

    目录 鸿蒙开发板(Neptune)开发教程-环境搭建-编译-烧录 Neptune简介 介绍特点 开发板参数 引脚 说明 开发环境搭建 linux编译环境搭建 python环境安装 hpm环境安装 wi ...

  8. [转]软件开发规范—模块开发卷宗(GB8567——88)

    做软件开发是有那么一套国准可参照的,当然就是那些文档了,这里列出一下所有软件开发的规范文档: 操作手册 用户手册 软件质量保证计划 软件需求说明书 概要设计说明书 开发进度月报 测试计划文档 测试分析 ...

  9. TuyaOS 开发教程-嵌入式开发套件

    0. 前言 ​ 智能时代的到来,让物与人的关系.物与物的关系更加密切.但是物联网行业种类复杂.接入环节冗长.设备规模以及数据量庞大等,都成为了物联网发展的难点.为此,涂鸦推出了一系列应用于IoT 领域 ...

最新文章

  1. python 2x xlrd使用merged_cells 读取的合并单元格为空
  2. 启明云端分享| 小明实测优化后的ESP32-S2点 3.92寸分辨率为320*320的彩屏刷新帧率
  3. pyqt5获取文本框里输入的值_实战PyQt5: 060-输入对话框QInputDialog
  4. sql求平均日活_杨学峰博客 | Flask Sqlarchemy实现按日、周、月统计并图表展示
  5. 搜索二维矩阵 II—leetcode240
  6. python遍历文件对象_Python文件常见操作实例分析【读写、遍历】
  7. python变量定义大全_详解python变量与数据类型
  8. tcp 接收端优雅的写法_如何更优雅地接收设计反馈
  9. 安装 RabbitMQ
  10. nlp项目:搭建一个简单的问答系统
  11. 离散数学 习题篇 —— 最小生成树
  12. Android Window/Window Z-Order/Surface/SurfaceView
  13. (位于 xx.exe 中)引发的异常
  14. 直达号PK公众号的背后还有哪些市场空间?
  15. (int*)、(int *)和(int **)的区别
  16. 3个小球放入4个盒子
  17. 一体化模拟器部署以及IOS操作基础
  18. Linux环境AES解密报错:Given final block not properly padded. Such issues can arise if a bad key is used dur
  19. aiem模型matlab,基于MIMICS模型的麦田地表土壤含水量反演研究
  20. 200A FS3L200R10W3S7FB11 EasyPACK 950V IGBT模块

热门文章

  1. smarty mysql demo_PHP Smarty模版简单使用方法
  2. usaco fencing the cows
  3. java常用的集合对象_java常用实体类、集合类
  4. python 3.7.732位安装步骤_python安装教程(Windows系统,python3.7为例)
  5. 上传图片被防火墙拦截_Web安全:文件上传漏洞
  6. mysql数据库名称sid_数据库sid 和数据库名
  7. php layui table,layui table 相关问题汇总
  8. 北航机器人研究所 裴旭_三年亏损近29亿!北航硕士痴迷平衡车,让“中国智造”走向世界...
  9. page分页php,Page分页函数
  10. 计算机网络技术社团纳新海报,精品社团纳新 | 加入计算机协会和我一起做些有意义的事儿吧~...