[精]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, fields
class 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 description
Can 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位.
[精]Odoo 8.0深入浅出开发教程-模块开发基础的更多相关文章
- STM32开发 -- 4G模块开发详解(转)
		STM32开发 -- 4G模块开发详解(1) STM32开发 -- 4G模块开发详解(2) STM32开发 -- 4G模块开发详解(3) STM32开发 -- 4G模块开发详解(4) 
- [转]软件开发规范—模块开发卷宗(GB8567——88)
		做软件开发是有那么一套国准可参照的,当然就是那些文档了,这里列出一下所有软件开发的规范文档: 操作手册 用户手册 软件质量保证计划 软件需求说明书 概要设计说明书 开发进度月报 测试计划文档 测试分析 ... 
- 勤拂拭软件 java web 开发教程(1) - 开发环境搭建
		勤拂拭软件系列教程 之 Java Web开发之旅(1) Java Web开发环境搭建 1 前言 工作过程中,遇到不少朋友想要学习jsp开发,然而第一步都迈不出,连一个基本的环境都没有,试问,如何能够继 ... 
- java web 开发教程(1) - 开发环境搭建
		勤拂拭软件系列教程 之 Java Web开发之旅(1) Java Web开发环境搭建 1 前言 工作过程中,遇到不少朋友想要学习jsp开发,然而第一步都迈不出,连一个基本的环境都没有,试问,如何能够继 ... 
- 移动应用产品开发-android开发 新闻模块开发 百度Frontia组件应用之分享
		这两天主要做了新闻模块的开发,做了新闻列表,新闻详情,数据结构解析,以及百度 Frontia 组件的研究. 新闻模块用的是开源中国的android开源代码里的代码,主要是模仿它的源码架构,首先打开是资 ... 
- 最简单的SAP云平台开发教程 - 如何开发UI5应用并运行在SAP云平台上
		选择Services Catalog,根据关键字搜索到WebIDE服务,点击超链接打开WebIDE: 进入workspace,选择Git->Clone Repository: 从我的github ... 
- 【Odoo 8开发教程】第一章:Odoo 8.0安装
		转载请注明原文地址:https://www.cnblogs.com/cnodoo/p/10779733.html odoo有三种常见的安装方式:打包程序安装.源码安装以及Docker镜像安装. 一:打 ... 
- 配置ubuntu 16.04.1 LTS odoo 10.0开发环境
		使用VMware Fusion 8.5.0创建ubuntu 64bit虚拟机:使用ubuntu-16.04.1-desktop-amd64.iso镜像缺省安装ubuntu,用户名odoo,密码1234 ... 
- 配置ubuntu 14.04.3 LTS odoo 9.0开发环境
		使用VMware Fusion 8.0.1创建ubuntu 64bit虚拟机:使用ubuntu-14.04.3-desktop-amd64.iso镜像缺省安装ubuntu,用户名odoo,密码1234 ... 
随机推荐
- 【Android】11.3 屏幕旋转和场景变换过程中GridView的呈现
			分类:C#.Android.VS2015: 创建日期:2016-02-21 一.简介 实际上,对于布局文件中的View来说,大多数情况下,Android都会自动保存这些状态,并不需要我们都去处理它.这 ... 
- C# 使用Nlog记录日志到数据库
			[摘要]Nlog是一个很不错的.NET日志记录组件,它可以将日志输出到控件台,保存到文本,也可以很方便的记录到数据库中.本文为你介绍C# 使用Nlog记录日志到数据库. Nlog是一个很不错的.NET ... 
- angular学习笔记(四)- input元素的ng-model属性
			input元素的ng-model属性: 用于将input的值和变量的值进行双向绑定 <!DOCTYPE html> <html ng-app> <head> < ... 
- web 安全问题(一):CSRF 攻击
			什么是CSRF CSRF是怎么产生的 CSRF的攻击对象 CSRG的攻击手段 CSRF的防御措施 什么是CSRF 全称是(Cross Site Request Forgery)跨站请求伪造.也就是恶意 ... 
- 李洪强漫谈iOS开发[C语言-054]-函数
			// // main.c // 02 翻译数字的优化 // // Created by vic fan on 2017/6/4. // Copyright © 2017年 李洪强. All r ... 
- 超烂的ELK之filebeat读取【已解决】
			搞了无数次的filebeat-->logstash今天栽了跟头 filebeat在读取如下文件的时候,openchgw.log 软连接speechgw.log.20170703183729文件 ... 
- 【转】Hadoop安全实践
			前言 在2014年初,我们将线上使用的 Hadoop 1.0 集群切换到 Hadoop 2.2.0 稳定版, 与此同时部署了 Hadoop 的安全认证.本文主要介绍在 Hadoop 2.2.0 上部署 ... 
- Class.getName和Class.getCanonicalName的区别
			对于一般的type来说,这二者没有区别,对于array和inner type,就有区别了,可以写代码亲测,如下: package simple; class Box { class Inner {} ... 
- tomcat java变量环境设置
			绿色版tomcat 手动启动startup.bat的时候出现一闪而过的状态.解决方法,配置startup.bat文件 @echo off SET JAVA_HOME=C:\Program Files ... 
- RTX——第16章 消息邮箱
			以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 前面几个章节主要给大家讲解了任务间的同步和资源共享机制,本章节为大家讲解任务间的通信机制消息邮箱,RTX ... 
