odoo开发教程一 环境搭建和入门

为什么要重写一个教程

google搜了一下互联网上目前还没有一份真正实用,免费的中文教程。曾经在博客园写过几篇,但是没能坚持下来,现在正好有时间,就争取写一个图文并茂,力求面面俱到的教程吧,也权当是对自己知识的一个重新梳理。

章节目录

  1. 第一章 环境的搭建及入门
  2. 第二章 字段类型和基本视图类型
  3. 第三章 继承与搜索
  4. [第四章 新API的介绍]
  5. [第五章 重载]
  6. [第六章 动作]

关于Odoo

笔者接触odoo已经有四五年的时间了,从最初的OpenERP 7到现在的odoo 12,中间有过一段时间的远离,现在机缘巧合下又重新出发。Odoo是一个优秀的开源ERP框架,有这诸多的优点,部署简单、开发迅速、可扩展性好,当然一个事物有有点就必定会有缺点,缺点就是语言小众(Python:怪我咯?),资料奇少,最重要的一点也是最致命的一点就是它真的只是一个框架,虽然有众多的第三方模块加成,但是真的无法做到开箱即用,这也就对它的潜在使用者造成了门楷,看起来美好,像用起来却不得不找专业的公司实施或者招一个懂行的人进行开发。

Odoo的国内市场,目前(2019)有了一个领航人,浪潮集团,可能会对国内的生态带了一些积极的影响。但是就目前的态势来看,浪潮的思路也是做SAAS模式。个人并不看好这种模式,Odoo社区版虽然免费,但实施起来却需要相当的持续的投入,这对企业的长远来说并不算是一个性价比高的选择。笔者曾经供职的一家企业,在2014年开始使用Odoo,后来因为技术的支持不到位(也许有资金层面的原因),现在据说已经退回到金蝶用友的软件了。对于国内一些靠Odoo实施生存的企业来说,个人也持悲观模式,其实Odoo入华已经年头不少了,从6.0(2012)开始国内就有先驱开始做这块的市场,现在7年已经过去了,依旧没有看到一家能够壮大的专业实施公司。这里边需要思考的东西挺多,当官方都吃不饱(甚至跑过来跟代理商抢饭吃)的时候,处在下游的公司就更难说活得美好了。

个人觉得,Odoo最好的使用模式,是公司或者集团内部,由IT团队进行支持开发,然后不断迭代,内化成自己公司的内部一套ERP系统是最合适的。IT团队懂技术,产品团队优化需求,再经过持续迭代和优化,最终能够成为一套不错的解决方案。因为IT团队本身就是需要投入,这样就能将成本摊平,提高软件使用的性价比。本系列教程也是从技术层面出发,希望能多的人能够了解到这套系统的架构,从中学到一些不错的思路,而对于商业化层面的东西,我只能说,偶尔兼个职也是不错的。

环境的搭建

关于Odoo的环境搭建,其实这里不想说太多了,网上关于如何搭建的教程真的挺多了。这里只提供一下笔者开发的模式。

个人使用的开发模式是,VM虚拟机+VSCode的方式,VM虚拟机安装Ubuntu系统,通过deb包的方式进行Odoo的安装,然后通过VM挂在共享文件夹,这样就可以实现在Win下开发,在Ubuntu上进行调试的模式。

关于调试,这是使用的命令行的方式,需要输出的时候就可以Print或者logger一下。

需要详细安装步骤的,请参考这里

第一个模块

本系列教程将告诉大家如何做一个书店,所以我们将给这个模块命名为book_store。模块的命名一定要体现出模块的用途,且不要跟已有的模块名重名,所以在模块前加上公司名是一个不错的选择。

1
odoo scaffold book_store .

这个命令是odoo提供的脚手架,scaffold是命令,后面跟模块名和模块路径,执行完命令的结果如下:

  • controllers文件夹主要是一些HTTP请求相关的业务逻辑。
  • models是模型文件夹,业务的模型都放在这里。
  • security 权限相关的文件。
  • views 视图文件夹,关于界面布局的逻辑在这里。
  • __init__ 熟悉python的都懂,不说了
  • __manifest__ 9.0之前叫__openerp__.py,Odoo模块必须的文件,包含必要的模块信息。

接下来我们修改一下模块的信息,修改__manifest__.py文件,如以下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# -*- coding: utf-8 -*-
{
'name': "book_store",

'summary': """
demo module for tutorial.""",

'description': """
This module is writing for who wants learn odoo developments.
""",

'author': "KevinKong",
'website': "http://mixoo.cn",

# Categories can be used to filter modules in modules listing
# Check https://github.com/odoo/odoo/blob/12.0/odoo/addons/base/data/ir_module_category_data.xml
# for the full list
'category': 'tutorial',
'version': '0.1',

# any module necessary for this one to work correctly
'depends': ['base'],

# always loaded
'data': [
'security/ir.model.access.csv',
'views/views.xml',
# 'views/templates.xml',
],
# only loaded in demonstration mode
'demo': [
'demo/demo.xml',
],
"application": True
}

关于这个字典里的属性,注释中大多都解释了。写完这个,我们可以验证一下Odoo是否能够正确加载我们的模块。

模块的路径需要写到配置文件中,如果是笔者这种安装方式,配置文件在/etc/odoo/odoo.conf

启动odoo后,打开debug模式(URL/web?debug),在应用-更新本地模块中点击更新:

然后再搜素book_store:

这样就说明odoo正确的加载了我们的模块。

第一个模型

模型对应的是数据库中的数据表,但是模型的概念比表跟多,很多属性不存储在数据库中。

我们新建一个书的模型,首先,书有多种属性,这里我们先写如下几种:

  • 名称
  • 作者
  • 日期
  • 定价

名称是Char类型,作者这里先设置为Char类型,日期是Datetime,定价就是Float。

1
2
3
4
5
6
7
class Book(models.Model):
_name = 'book_store.book'

name = fields.Char('名称', help='书名')
author = fields.Char('作者', help='作者')
date = fields.Datetime("出版日期", help="日期")
price = fields.Float("定价", help="定价")

然后我们需要给这个模型设置一个界面,编辑views文件夹下的view.xml文件,添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<odoo>
<data>
<!-- explicit list view definition -->

<record model="ir.ui.view" id="book_store.list">
<field name="name">图书列表</field>
<field name="model">book_store.book</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="author"/>
<field name="date"/>
<field name="price"/>
</tree>
</field>
</record>

<record id="book_store.book_form" model="ir.ui.view">
<field name="name">图书</field>
<field name="model">book_store.book</field>
<field name="arch" type="xml">
<form string="图书详情" class="">
<sheet>
<h1>
<field name="name" invisible="0"/>
</h1>
<group>
<field name="author" invisible="0"/>
<field name="date" invisible="0"/>
<field name="price" invisible="0"/>
</group>
</sheet>
</form>
</field>
</record>


<!-- actions opening views on models -->

<record model="ir.actions.act_window" id="book_store.action_window">
<field name="name">图书</field>
<field name="res_model">book_store.book</field>
<field name="view_mode">tree,form</field>
</record>


<!-- server action to the one above -->
<!--
<record model="ir.actions.server" id="book_store.action_server">
<field name="name">book_store server</field>
<field name="model_id" ref="model_book_store_book_store"/>
<field name="state">code</field>
<field name="code">
action = {
"type": "ir.actions.act_window",
"view_mode": "tree,form",
"res_model": self._name,
}
</field>
</record>
-->

<!-- Top menu item -->

<menuitem name="浪矢书店" id="book_store.menu_root"/>

<!-- menu categories -->

<menuitem name="书店" id="book_store.menu_book" action="book_store.action_window" parent="book_store.menu_root"/>
<menuitem name="分类" id="book_store.menu_category" parent="book_store.menu_root"/>

<!-- actions -->
<!--
<menuitem name="List" id="book_store.menu_1_list" parent="book_store.menu_1" action="book_store.action_window"/>
<menuitem name="Server to list" id="book_store" parent="book_store.menu_2" action="book_store.action_server"/>
-->
</data>
</odoo>

XML文件写完以后,在应用-模块中点击升级模块对模块进行升级。

当修改了py文件时,需要重启odoo进程,而修改了xml等静态文件则需要升级模块。

升级完成后,进入odoo发现没有我们写完的menu。这是因为,我们只创建了model却没有给任何一个组赋予访问这个模型的权限,因此我们无权查看这个模块的界面。

给book模型添加权限,编辑security文件夹中的ir.model.access.csv文件,csv文件从左右到依次是,id,名称,模型id,组ID,读权限,写权限,创建权限、删除权限。

其中模型是model_加上模型名组成的,其中的点号要换成下划线。

1
2
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_book_store_book,book_store.book,model_book_store_book_store,base.group_user,1,1,1,1

然后我们重新升级模块。

就可以看见我们自定义的菜单出来了:

点击菜单我们可以创建图书:

和查看图书列表:

这样我们的第一个模块就完成了。

开发者调试模式

正常情况下,代码文件发生改变需要重启odoo进程或升级模块,对开发者来说,频发的Ctrl+C和upgrade有时候比较费事,Odoo提供了一种免重启的模式,当代码文件发生变化时自动重载并更新视图文件,大大简化了开发的步骤。

启动这个模式的命令是在启动odoo的命令后添加一个–dev参数:

1
odoo -c /etc/odoo/odoo.conf --dev=all

注意:可能会碰到下面的错误:

1
'inotify' module not installed. Code autoreload feature is disabled

这是因为缺少依赖库inotify, 使用pip命令安装即可:

1
pip install inotify
你的支持我的动力