当前位置: 首页 > 编程日记 > 正文

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

參考资料点击这里.

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

相关文章:

Java基础知识强化之IO流笔记41:字符流缓冲流之复制文本文件案例02(使用 [ newLine() / readLine() ] )(重要)...

1. 使用字符流缓冲流的特殊功能 [ newLine() / readLine() ] 需求&#xff1a;把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中 数据源&#xff1a; a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader -- FileReader -- BufferedReader 目的地&#xff1a;…

Ant Design Pro 跳转路由 传参数,接收参数

umi/link 通过声明的方式做路由跳转。 例子: import Link from umi/link;export default () => {<div>/* 普通使用 */<Link to="/list">Go to list page</Link>/* 带参数 */<Link to="/list?a=b">Go to list page</Lin…

编写react组件_React组件的“黄金法则”如何帮助您编写更好的代码

编写react组件以及钩子如何发挥作用 (And how hooks come into play) Recently I’ve adopted a new philosophy that changes the way I make components. It’s not necessarily a new idea but rather a subtle new way of thinking.最近&#xff0c;我采用了一种新的理念&a…

js验证函数摘录

/**本文摘自&#xff1a;http://www.cnblogs.com/rob0121/articles/1776298.html* js各种表单数据验证*/ /**************************************************************************************/ /*************************************数字的验证*********************…

React for循环渲染组件

通常你需要在一个组件中渲染列表。或者循环遍历渲染相同的多个组件,下面看看怎么实现: render() {const options = this.state.data.map(d => <Option key={d.value}>{d.text}</Option>);return (<SelectshowSearchvalue={this.state.value}placeholder={t…

让电脑的灵魂跟你走

想必我这个题目一出来&#xff0c;大家就知道我想写的是电脑远程控制了。 电脑远程控制是为了方便人们随时随地访问自己的电脑&#xff0c;从而进行更加灵活高效的工作。最常见的远程控制是我们利用客户端直接进入后台操作命令行界面。也就是终端shell。 电影里面&#xff0c;黑…

您尝试打开的文件_您是否尝试过重新打开软件团队的身份?

您尝试打开的文件by Victoriya Kalmanovich由Victoriya Kalmanovich 您是否尝试过重新打开软件团队的身份&#xff1f; (Have you tried turning your software team’s identity off and on again?) This series portrays my experience as an R&D group leader of a gr…

vijos 1006 晴天小猪历险记之Hill——数字三角形的终极变化

题目链接&#xff1a;https://vijos.org/p/1006 数字三角形原题看这里&#xff1a;http://www.cnblogs.com/huashanqingzhu/p/7326837.html 背景 在很久很久以前&#xff0c;有一个动物村庄&#xff0c;那里是猪的乐园&#xff08;^_^&#xff09;&#xff0c;村民们勤劳、勇敢…

电磁学讲义6:高斯定理计算电场

高斯定理是电场力平方反比定律和线性叠加原理的直接结果。也可以由高斯定理作为基本规律导出库仑定律。这说明高斯定理和库仑定律是不同形式的表示电荷和电场关系的同一规律。库仑定律可以使我们从电荷分布求出电场分布&#xff0c;高斯定理可以使我们从电场分布求出电荷分布。…

ant table表格整行点击事件并获取当前行的数据

实现效果:点击表格中某一行,或者点击表格中某一行的一个字段,获取当前行的 item 下标数据,并用 Link 标签传参,下一个页面接收的实现。 如果使用 router 跳转路由传参,需要导入 import router from umi/router; 如果用 Link 跳转路由传参,需要导入 import Link from u…

以太坊公链私链_如何使用以太坊构建汽车制造供应链系统

以太坊公链私链by Marcelo Russi Mergulho由Marcelo RussiMergulho 如何使用以太坊构建汽车制造供应链系统 (How to build a car manufacturing supply chain system using Ethereum) Here at Daitan we are always looking for new technologies that can help our clients s…

微信一次性订阅消息

微信一次性订阅消息官方文档&#xff1a;消息管理>发送一次性订阅消息 开发者可以通过一次性订阅消息授权让微信用户授权第三方移动应用&#xff08;接入说明&#xff09;或公众号&#xff0c;获得发送一次订阅消息给到授权微信用户的机会。授权微信用户可以不需要关注公众号…

react控制组件的显示或隐藏, 根据state判断元素显示隐藏 , setState不实时生效解决方法

代码实现功能&#xff1a;根据 state 中的值判断子组件显示或隐藏&#xff0c;因为 setState 不是及时生效的&#xff0c;所以不做显示隐藏判断会报错。 render() {// 客户经理循环组件function CommentSpan(props){const numbers props.managers;if(!numbers) return;const l…

关于R语言plyr包的安装问题

平时安装R包都是从Rstudio中进行的&#xff0c;今天在装plyr包的时候&#xff0c;Rstudio一直报错&#xff0c;示例如下&#xff1a; 是不是很无语啊&#xff0c;搞了半天不知所以然&#xff0c;然后突发奇想从Rgui中安装试下&#xff0c;没想到轻轻松松就成功了&#xff0c;示…

regexp 好汉字符串_如何在JavaScript中使用RegExp确认字符串的结尾

regexp 好汉字符串by Catherine Vassant (aka Codingk8)由凯瑟琳瓦森(Catherine Vassant)(又名Codingk8) 如何在JavaScript中使用RegExp确认字符串的结尾 (How to use a RegExp to confirm the ending of a String in JavaScript) Using the Regexp ?️ constructor使用Regex…

【转】浅谈分布式锁

前言 随着互联网技术的不断发展&#xff0c;数据量的不断增加&#xff0c;业务逻辑日趋复杂&#xff0c;在这种背景下&#xff0c;传统的集中式系统已经无法满足我们的业务需求&#xff0c;分布式系统被应用在更多的场景&#xff0c;而在分布式系统中访问共享资源就需要一种互斥…

php中的抽象类(abstract class)和接口(interface)

一、 抽象类abstract class 1 &#xff0e;抽象类是指在 class 前加了 abstract 关键字且存在抽象方法&#xff08;在类方法 function 关键字前加了 abstract 关键字&#xff09;的类。 2 &#xff0e;抽象类不能被直接实例化。抽象类中只定义&#xff08;或部分实现&#xff0…

React 父组件给子组件传值,子组件接收

父组件传值代码&#xff1a; render() {return (<div>{this.state.list?(<GeomLine list{this.state.list}/>):null}</div>);} 子组件接收代码&#xff1a; class GeomLine extends Component {// 在组件接收到一个新的 prop (更新后)时被调用。这个方法在…

unity 灯笼_如何创建将自己拼成文字的漂亮灯笼

unity 灯笼In this tutorial, we will go through how to create a group of festival lanterns that arrange themselves into the words you choose. An online demo can be found here.在本教程中&#xff0c;我们将介绍如何创建一组节日灯笼&#xff0c;这些灯笼将自己布置…

Android PackageManager packages.xml文件格式

packages.xml文件存放在/data/system目录下 该文件记录了系统中所有应用程序的包管理相关信息 PmS根据该文件进行包管理的各种操作 标签名称所包含的值举例last-platform-versioninternal"17" external"17"<permission-trees />暂时不使用<…

tplink wr886n v5.0 ttl 接线方法

我的倒是有ttl信息,但是全是乱码,换过RX和TX,也换过串口速率都没用,附上TTL接线图.2016-11-02今天晚上终于搞定了ttl了,步骤如下:1.先将串口波特率改为117500(推荐使用Putty).如果可以了就不用第二步了2.将usb转ttl转接板上的rx和tx的指示灯干掉,可以留下电源指示灯详细教程见s…

React子组件给父组件传值, 父组件引用子组件并给子组件传值

本博客代码是 React 父组件和子组件相互传值的 demo;实现封装一个折线图,折线图选择下拉框,获取下拉框点击的值并且传给父组件根据下拉框筛选的条件更新视图;效果图如下: 父组件代码: 代码解析:父组件 Parent 引用子组件 Sub ,传递了 list 组件给子组件,并且接收子组件…

我如何使用深度学习通过Fast.ai对医学图像进行分类

by James Dietle詹姆斯迪特尔(James Dietle) Convolutional Neural Networks (CNNs) have rapidly advanced the last two years helping with medical image classification. How can we, even as hobbyists, take these recent advances and apply them to new datasets? W…

Java——基础

1.数据类型 int&#xff0c;short&#xff0c;byte&#xff0c;long double&#xff0c;float char&#xff0c;String 2.变量 int var; var 12; int var1 12;final int v1 0; //常量 C/C变量的声明和定义是分开的&#xff0c;JAVA不区分。 //c/c extern int a; //声明 …

Gradle系列教程之依赖管理

这一章我将介绍Gradle对依赖管理的强大支持&#xff0c;学习依赖分组和定位不同类型仓库。依赖管理看起来很容易&#xff0c;但是当出现依赖解析冲突时就会很棘手&#xff0c;复杂的依赖关系可能导致构建中依赖一个库的多个版本。Gradle通过分析依赖树得到依赖报告&#xff0c;…

Ant Design Pro 登录流程以及路由权限设置

登录流程: 1.ant 框架最外层套了 SecurityLayout 布局 SecurityLayout 中判断用户是否登录,做自动跳转路由处理。 里面的 currentUser 和 currentUser.userid 很关键,是判断登录状态的值. 2.currentUser 是通过 src/models/user 中 fetchCurrent 绑定 type saveCurrentUs…

初级开发人员的缺点_这是我想放弃初级开发人员时所做的事情

初级开发人员的缺点Coding is hard. Really hard. There are times when you’ll think “this is amazing! I love this!”编码很难。 真的很难。 有时您会认为“这太神奇了&#xff01; 我喜欢这个&#xff01;” But you’ll also have the not so amazing times. The time…

C#之 HashSet(临时笔记,未参考资料,请慎重)

HashSet是一个集合&#xff0c;类似于DataSet,但是其主要用途是用来存放同一种类型的元素&#xff08;string、row、table等&#xff09;&#xff0c;如果添加的元素跟定义时初始的类型不一致&#xff0c;就会直接编译失败。 例如&#xff1a; HashSet<string> hsnew Has…

Ant Design of React从入门到开发教程

Ant Design Pro 是一个企业级中后台前端/设计解决方案。 目录: 一:开发前的准备 二:创建页面 三:创建组件并引用 四:封装网络请求和网络请求走向 五:登录流程以及路由权限设置 六:父组件和子组件相互传值和接收 七:for 循环渲染组件 Ant Design Pro 全家桶技术…

适合初学者的数据结构_数据结构101:数组-初学者的直观介绍

适合初学者的数据结构了解您每天使用的数据结构。 (Get to know the data structures that you use every day. ) Welcome! Let’s Start with some Vital Context. Let me ask you this: ✅ Do you listen to music on your smartphone?✅ Do you keep a list of contacts on…