第二章 Hello Odoo

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

脚手架

下面的命令可以帮助我们创建一个标准模块所需要的全部文件:

odoo scaffold book_store .

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

然后我们再根据我们的实际情况对其中的某些文件进行修改就可以了。

odoo模块结构

  • controllers: 主要是一些HTTP请求相关的业务逻辑。
  • models: 模型文件夹,业务的模型都放在这里。
  • security: 权限相关的文件。
  • views: 视图文件夹,关于界面布局的逻辑在这里。
  • static: 静态文件夹,前端使用的qweb文件和js、css文件和图片等静态文件放到这个文件夹内。
  • __init__:熟悉python的都懂,不说了
  • __manifest__: 9.0之前叫_openerp_.py,Odoo模块必须的文件,包含必要的模块信息。

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

# -*- 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://www.odoomommy.com",

    # 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': '15.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
}

常见的manifest中的键值信息有:

  • name:模块名称,在模块列表中显示的名称,仅作名称使用,没有限制条件。
  • summary: 模块的摘要信息,通常比较简短。
  • description: 模块的详细信息,用于说明模块如何使用,说明文档等内容,可以放置图文信息以帮助用户更好地使用模块。
  • author:作者信息
  • website:模块的主页
  • category: 模块的分类,没有限制,可以自己新加分类,建议根据模块的用途进行分类。
  • version:版本信息, 推荐在版本中包含odoo的版本信息,例如15.1
  • data:数组,需要加载的静态文件路径,通常放的是视图文件、权限文件csv和qweb模板文件的路径。
  • demo:演示数据
  • application: 布尔值,标示本模块是否为一个应用。
  • qweb: qweb文件路径
  • installable: 布尔值,标示本模块是否可以被安装。
  • external_dependencies: 模块的外部依赖,通常用来填写Python的依赖包。({'python':['openpyxl','simplejson']})

加载模块

写完这个,我们可以验证一下Odoo是否能够正确加载我们的模块。

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

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

module

然后再搜索book_store:

bk

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

第一个模块

定义模型

odoo开发的第一步就是要先建立自己的数据模型,也就是我们常说的models,模型对应的是数据库中的数据表,但是模型的概念比表更多,很多属性并不存储在数据库中。现在,我们先建一个基础的图书信息,假设目前我们的图书只采集了如下几个属性:

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

名称是字符串,因此使用Char类型,作者这里先设置为Char类型,后期会更改为Many2one类型,日期是Datetime,定价就是Float。因此,我们的模型可以写成下面这样:

class Book(models.Model):
    _name = 'book_store.book'

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

odoo所有的持久化模型都要继承自models.Model类,当然也存在于另外一种非持久化的类,这个等到后面再详细介绍。这里,我们先简单记住,所有的要在数据库中建立表结构的对象,都要继承自models.Model类。

定义视图文件

odoo能够快速开发应用的一个很重要的原因就是它封装了很多常见的操作,像创建、编辑、搜索和删除等,默认情况下,我们不用重写这些逻辑就可以使用,甚至不用写视图文件。但是为了说明起见,我们这里还是要编写一些视图文件。

编辑views文件夹下的view.xml文件,添加如下代码:

<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="图书详情">
          <sheet>
            <h1>
              <field name="name"/>
            </h1>
            <group>
              <field name="author"/>
              <field name="date"/>
              <field name="price"/>
            </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>

    <!-- 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_book" action="book_store.action_window" parent="book_store.menu_root"/>


  </data>
</odoo>

加载更改后的模块

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

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

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

添加模型的访问权限

默认情况下,我们不拥有对新创建的对象的访问权限,因此我们需要在安装模块时,给指定的用户添加访问权限。odoo提供的方式之一,就是按照一定的格式编写一个csv文件,声明在manifest文件中。这样当升级模块时,odoo就能够读取csv文件中的权限设置,并写入到数据库中。

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

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

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
  • id: 该权限记录的唯一标示
  • name: 访问权限的名字
  • model_id:id: 模型名称,格式为 模块名.模型名
  • group_id:id: 设置的用户组,格式为 模块名.组xml_id
  • perm_read: 对应访问权限
  • perm_write: 对应编辑权限
  • perm_create: 对应创建权限
  • perm_unlink: 对应删除权限

后四列,当为1时表示拥有这个权限,0代表没有权限。

设置完权限,我们重新升级模块,就可以看见我们自定义的菜单出来了:

app

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

book

查看图书列表:

list

开发者调试模式

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

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

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

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

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

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

pip install inotify

总结

本章,我们学习了一个模块的基本组成结构,并尝试编写了我们的第一个模块。下一步,我们将认识odoo中模型的基本字段类型和基本的视图类型。

本教程示例代码

results matching ""

    No results matching ""