Odoo14开发者指南第三章-创建Odoo附加模块【翻译】

现在我们已经有了一个开发环境,也知道如何管理Odoo服务器实例和数据库,下面我们可以学习如何创建Odoo附加模块。

我们在本章的主要目标是了解一个附加模块的结构,以及向其添加组件的典型渐进式学习路线。本章教程名称中提到的各种组件将在后续章节中广泛介绍。

在这章中,包含以下教程:

技术要求

在本章中,希望您已经安装了Odoo,并按照《第一章-安装Odoo开发环境》中的方法进行操作。此外,您还需要熟悉发现和安装额外的附加模块,如《第二章-管理Odoo服务器实例》中所述。

本章使用的所有代码你可以到以下GitHub仓库下载:

https://github.com/PacktPublishing/Odoo-14-Development-Cookbook-Fourth-Edition/tree/master/Chapter03

什么是Odoo附加模块

处理Odoo框架的代码,Odoo的所有代码库都是以模块的形式打包的。这些模块可以随时从数据库中安装或卸载。这些模块有两个主要目的。要么你可以添加新的应用程序/业务逻辑,要么你可以修改现有的应用程序。简单地说,在Odoo中,一切都以模块开始和结束。

Odoo被各种规模的公司所使用,每个公司都有不同的业务流程和要求。为了处理这个问题,Odoo将应用程序的功能分割成不同的模块。这些模块可以根据需求在数据库中加载。基本上,用户可以启用/禁用这些模块的功能。因此,同一软件可以根据不同的要求进行调整。请看以下Odoo模块的截图;栏目中的第一个模块是主应用程序,其他模块是为了在该应用程序中添加额外的功能。要获得按应用类别分组的模块列表,请进入应用菜单,应用按类别分组:

Grouping apps by category

如果你计划在Odoo中开发新的应用程序,你应该为各种功能创建边界。这对于将你的应用程序划分为不同的附加模块非常有帮助。现在你知道了Odoo中附加模块的目的,我们可以开始构建自己的附加模块了。

创建和安装新的附加模块

在以下教程中我们会创建一个新的模块使其可以被Odoo实例识别并安装。

准备工作

首先我们需要一个正在运行的Odoo实例,如果你进行了《第一章-安装Odoo开发环境》的操作,你的Odoo应该安装在 ~/odoo-dev/odoo 中。为了便于讲解教程,我们假设你的实例已经安装在以上目录中,当然你也可以根据你的喜好进行修改。

我们还需要一个目录来存放我们开发的Odoo模块。为了方便讲解,我们会使用odoo实例目录下的 local-addons 目录作为该目录,目录路径为 ~/odoo-dev/local-addons

操作步骤

我们将创建一个小的附加模块,用于管理图书馆的图书列表来作为本章的例子。

使用以下步骤来创建和安装一个新的附加模块:

  1. 进入Odoo实例目录并创建一个新的目录来存放我们开发的模块:

    1
    2
    $ cd ~/odoo-dev
    $ mkdir local-addons
  2. 为新模块选择一个技术名称,并为模块创建一个同名的目录,例如我们使用 my_library 作为模块名称:

    1
    $ mkdir local-addons/my_library

    一个模块的技术名称必须是一个有效的Python标识符,它必须以字母开头并且只包含字母、数字和下划线字符。最好在模块名中只是用小写字母。

  3. 添加__init__.py文件使模块能被Python导入:

    1
    $ touch local-addons/my_library/__init__.py
  4. 添加一个最小的模块清单,以便Odoo检测到它是一个附加模块。在my_library文件夹中,创建一个__manifest__.py文件,其中有这样一行:

    1
    {'name': 'My Library'}
  5. 开启你的Odoo实例,在addons-path中添加我们模块目录:

    1
    $ odoo/odoo-bin --addons-path=odoo/addon/,loacl-addons/

    如果使用了--save选项,add-ons 路径会被保存到配置文件中。下次启动服务器时,如果没有提供add-ons路径选项,将使用这个选项。

  6. 要使新模块在你的Odoo实例中可用,使用管理员登录Odoo,在关于框中启用开发者模式,在应用顶部菜单中选择更新应用程序列表。现在,Odoo应该能识别我们的Odoo模块了:

    Dialog to update the app list

  7. 选择顶部的应用菜单,在右上角的搜索栏中,删除默认的应用筛选器,搜索my_library。点击安装按钮,即可完成安装。

运行原理

一个Odoo模块目录包含代码文件和其他资源文件。文件夹的名称使用模块的技术名称。模块的清单文件中的name的value也是模块的技术名称。

__manifest__.py文件是模块的清单文件。这包含一个Python字典,其中包含模块元数据,包括类别、版本、它所依赖的模块,以及它将加载的数据文件列表。在本节教程中,我们使用了一个最小的清单文件,但在实际的模块中,我们将需要其他重要的键。这些将在下一节完成附加模块清单中再介绍。

模块的目录必须是Python能导入的,因此该目录中需要有__init__.py文件,该文件甚至可以是空文件。要加载一个模块,Odoo服务器将导入它。这将导致__init__.py文件中的代码被执行,所以它可以作为运行模块Python代码的入口点。由于这个原因,它通常会包含导入语句来加载模块的Python文件和子模块。

已知的模块可以使用--init或-i选项直接从命令行安装。例如,如果你想安装crm和网站应用,你可以使用-i crm,website。当你从当时提供的add-ons路径上找到的模块创建一个新的数据库时,这个列表会被初始化。可以在现有的数据库中通过更新模块列表菜单进行更新。

完善附加模块的清单文件

清单文件是Odoo模块的重要的一部分。它包含了关于附加模块的重要元数据,并声明了应该加载的数据文件。

准备工作

我们应该有一个模块来工作,已经包含一个__manifest__.py清单文件。你可能想按照前面的配方来提供这样一个模块来工作。

操作步骤

我们将为我们的模块添加一个清单文件和图标:

  1. 创建一个清单文件__manifest__.py,编辑文件如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    {
    'name': "My library",
    'summary': "Manage books easily",
    'description': """
    Manage Library
    ==============
    Description related to library.
    """,
    'author': "Your name",
    'website': "http://www.example.com",
    'category': 'Uncategorized',
    'version': '13.0.1',
    'depends': ['base'],
    'data': ['views/views.xml'],
    'demo': ['demo.xml'],
    }
  2. 选择一个PNG格式的图片复制到static/description/icon.png

工作原理

清单文件中的内容是一个常规的Python字典,有键和值。我们最常用的键如下:

  • name:模块的名称。
  • summary:这是带有单行说明的副标题。
  • description:这是一个以纯文本或 ReStructuredText (RST) 格式书写的长描述。它通常由三个引号包围,在 Python 中用于限定多行文本。对于RST的快速入门参考https://docutils.sourceforge.io/docs/user/rst/quickstart.html
  • author:这是一个带有作者姓名的字符串。当有多个作者时,通常的做法是用逗号来分隔他们的名字,但注意它仍然应该是一个字符串,而不是一个Python列表。
  • website:这是一个URL,以了解作者和模块的更多信息。
  • category:用于组织模块,可用的标准别名列表可参考https://github.com/odoo/odoo/blob/13.0/odoo/addons/base/data/ir_module_category_data.xml。你也可以定义其他类别名称。
  • version:这是模块的版本号,它可以被Odoo应用商店检查以安装模块的较新版本。如果版本号不是以Odoo版本号(例如13.0),则会自动添加。不过,如果你明确说明Odoo的目标版本,例如使用13.0.1.0.0或13.0.1.0,而不是1.0.0或1.0,会更有参考价值。
  • depends:这是一个直接依赖的模块的技术名称列表,如果你的模块不依赖任何其他附加模块,则至少依赖 base 模块。不要忘记包括任何定义XML ID、视图或模型的模块,这些模块被该模块引用。这将确保它们都以正确的顺序加载,避免出现难以预计的错误。
  • data:这是一些用于安装和升级时加载的文件的路径列表。这些路径是相对与模块目录的相对路径。通常情况下,这些文件都是XML和CSV文件,但也有可能是YAML数据文件。这些将在第六章-管理模块数据中详细讨论。
  • demo:这是演示数据文件的相对路径列表,只有在创建数据库时启用了演示数据时才会加载这些数据。

用作模块图标的文件位于static/description/icon.png

Odoo在不同的主要版本之间会有很大的变化,所以为一个主要版本建立的模块在没有转换和迁移工作的情况下不可能与下一个版本兼容。因此,在安装模块之前,一定要确定模块的Odoo目标版本。

扩展内容

也可以用一个单独的描述文件来代替清单文件中定义的长描述,从8.0版本开始,可以用README文件代替,扩展名为.txt、.rst或.md(markdown)。此外,在模块中包含一个description/index.html文件。

HTML描述会覆盖清单文件中的长描述。

以下是一些常用的其他键:

  • licence:默认值是LGPL-3,用于定义模块的许可证,其他可能的许可包括 AGPL-3Odoo Proprietary License v1.0* (主要用于付费应用)和 Other OSI Approved Licence
  • application:该值如果为True,则模块为应用,通常情况下用于功能区的核心模块。
  • auto_install:该值如果为True,表示它是一个胶水模块,当所有的依赖项都安装完毕后,它会自动安装。
  • installable:默认值为True,表示该模块可以被安装。
  • external_dependencies:一些Odoo模块内部使用Python/bin库。如果你的模块使用了这样的库,你需要把它们放在这里。如果所列出的模块没有安装在主机上,这将阻止用户安装模块。
  • {pre_init, post_init, uninstall}_hook:这是一个Python函数钩子,在安装/卸载时被调用。更详细的例子,请参考第8章,高级服务器端开发技术。

以下是一些特殊的键,用于app商店的:

  • price:这个键用于设置你的附加模块的价格,该值应该设置为整型值,如果为空则表示你的应用是免费的。
  • currency:币别,可用的值包括USD和EUR。默认值为EUR。
  • live_test_url:如果你想提供一个在线测试的URL,你可以使用这个键,设置后在App商店上会显示Live Preview按钮。
  • iap:如果这个模块提供IAP服务,可以使用这个键设置你的IAP开发者密钥。
  • images:图片的路径,用于设置在Odoo的App商店上显示你的App封面的图片。

组织附加模块的文件结构

一个附加模块包含代码文件和其他资源文件,例如XML文件和图片文件,对于其中的大部分文件,我们可以自由选择放在模块目录内的位置。

但是,Odoo在模块结构上使用了一些约定,所以建议遵循这些约定。

准备工作

我们希望有一个附加模块目录,里面只有__init__.py__manifest__.py文件。在这个教程中,我们假设它是local-addons/my_library

操作步骤

执行以下步骤创建附加模块的基本框架:

  1. 创建代码文件的目录:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $ cd local-addons/my_library
    $ mkdir models
    $ touch models/__init__.py
    $ mkdir controllers
    $ touch controllers/__init__.py
    $ mkdir views
    $ touch views/views.xml
    $ mkdir security
    $ mkdir wizard
    $ touch wizard/__init__.py
    $ mkdir report
    $ mkdir data
    $ mkdir demo
    $ mkdir i18n
  2. 编辑模块根目录的__init__.py,以便加载子目录中的代码:

    1
    2
    from . import controllers
    from . import wizard

我们应该会得到一个包含最常用的目录的结构,类似于这个my_library模块的结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
├── __init__.py
├── __manifest__.py
├── controllers
│ └── __init__.py
├── data
├── demo
├── i18n
├── models
│ └── __init__.py
├── security
├── static
│ ├── description
│ └── src
│ ├─ js
│ ├─ scss
│ ├─ css
│ └ xml
├── report
├── wizard
│ └── __init__.py
└──views
└── __init__.py

运行原理

为了提供一些背景,一个Odoo附加模块可以有三种类型的文件。

  • Python代码由__init__.py文件加载,其中导入了.py文件和代码子目录。包含Python代码的子目录,则需要自己的__init__.py文件。
  • __manifest__.py模块清单文件的data和demo键中要声明的数据文件才能加载,通常是用户界面、夹具数据和演示数据的XML和CSV文件。也可能有YAML文件,它可以包含一些程序指令,在模块加载时运行,例如,以编程方式而不是静态地在XML文件中生成或更新记录。
  • Web资源文件,如JavaScript代码和库、CSS、SASS和QWeb/HTML模板。这些文件用于构建UI部件和管理用户在这些UI元素中的操作。这些都是通过一个XML文件来声明的,这个XML文件是扩展主模板的,它将这些资产添加到Web客户端或网站页面中。

附加模块文件将被组织到以下目录中:

  • models/ 包含后台创建模型及其业务逻辑的代码文件。每个模型建议使用一个与模型同名的文件,例如,library_book.py代表library.book模型。这些内容在《第4章-应用模型》中会有深入的阐述。
  • views/ 包含用户界面的actions、forms、list等XML文件。如模型,建议每个模型都有一个文件。网站模板的文件名应以 _tmplate 为后缀。后台视图在《第九章-后台视图》中讲解,网站视图在《第十四章-CMS网站开发》中讲解。
  • data/ 包含模块初始化的数据文件,数据文件将在《第六章-管理模块数据》中讲解。
  • demo/ 包含模块演示数据的数据文件,这些数据用于测试、培训和模块评估。
  • i18n/ 是Odoo寻找翻译.pot和.po文件的地方。更多细节请参考《第十一章-国际化》。这些文件不需要在清单文件中提及。
  • security/ 包含定义访问控制列表的数据文件,通常是一个ir.model.access.csv文件,也可能是一个XML文件,用于定义行级安全的访问组和记录规则。请看《第十章-安全访问》了解更多细节。
  • controllers/ 包含了网站控制器以及提供该类功能的模块的代码文件。Web控制器在第《十三章-Web服务器开发》中有所涉及。
  • static/ 是所有网站资源文件放置的地方。与其他目录不同的是,这个目录名不仅仅是一个约定俗成的名称。这个目录里面的文件是公开的,不需要用户登录就可以访问。这个目录主要包含JavaScript、样式表和图片等文件。它们不需要在模块清单中声明,但要在网页模板中必须要提及。这一点在《第十四章-CMS网站开发》中会详细讨论。
  • wizard/ 包含所有与向导相关的文件。在Odoo中,向导是用来保存中间数据的。我们在《第八章-高级服务器端开发技术》中学习更多关于向导的知识。
  • report/ Odoo提供了一个生成PDF文件的功能,如销售订单和发票。这个目录下存放了所有与PDF报表相关的文件。我们将在《第十二章-自动化、工作流、电子邮件和打印》中了解更多关于PDF报告的内容。

当为模块添加新文件时,不要忘记在__manifest__.py文件(数据文件)或__init__.py文件(代码文件)中声明它们,否则这些文件将被忽略并不会被加载。

添加模型

模型定义了我们业务应用程序将使用的数据结构。本节教程向您展示了如何在模块中添加一个基本模型。

实现步骤

要添加一个新的模型,我们需要添加一个描述它的Python文件,然后升级附加模块(或者安装它,如果还没有安装的话)。使用的路径是相对于我们的附加模块的位置(例如,~/odoo-dev/local-addons/my_library/)。

  1. 添加models/library_book.py Python文件,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    from odoo import models, fields
    class LibraryBook(models.Model):
    _name = 'library.book'
    name = fields.Char('Title', required=True)
    date_release = fields.Date('Release Date')
    author_ids = fields.Many2many(
    'res.partner',
    string='Authors'
    )
  2. 添加一个Python初始化文件models/__init__.py,代码如下:

    1
    from . import library_book
  3. 编辑模块的Python初始化文件来加载models/目录:

    1
    from . import models
  4. 通过命令行或用户界面的Apps菜单升级Odoo模块。如果你在升级模块时仔细观察服务器日志,你应该会看到以下一行:

    1
    odoo.modules.registry: module my_library: creating or updating database table

在这之后,新的 library.book 模型应该在我们的 Odoo 实例中可用。有两种方法可以检查我们的模型是否已经被添加到数据库中。

第一种方法,你可以在Odoo用户界面中查看。计划开发者工具,打开菜单的设置->技术->数据库结构->模型,在这里搜索library.book模型。

第二种方法是检查PostgreSQL数据库中的表项,你可以在数据库中搜索library_book表。在下面的示例代码中我们使用test-14.0作为我们的数据库。然而,在以下的命令中你也可以替换你的数据库名称:

1
2
$ psql test-14.0
test-14.0# \d library_book;

运行原理

我们的第一步是创建一个Python文件,其中创建了我们的新模块。

Odoo框架有自己的Object Relational Mapping(ORM) 框架。这个ORM框架提供了对PostgreSQL数据库的抽象。通过继承Odoo Python类Model ,我们可以创建自己的模型(表)。当定义一个新模型时,它也会被添加到一个中央模型注册表中。这使得其他模块以后更容易对其进行修改。

模型有一些以下划线为前缀的通用属性。最重要的是_name ,它提供了一个唯一的内部标识符,将在整个Odoo实例中使用。ORM框架会根据这个属性生成数据库表。在本节中我们使用了_name = ‘library.book’ 。基于此属性,ORM框架将创建一个名为library_book 的新表。请注意,ORM框架通过替换_name属性的值的._来创建表名。

模型字段被定义为类属性。我们首先定义name 字段,字段类型为Char 。模型有这个字段很方便,因为默认情况下,它被其他模型引用时用作记录描述。

我们还使用了一个关系字段的示例author_ids 。这定义了Library Books 与其partner之间的多对多关系。一本书可以有很多作者,每个作者可以写很多书。

关于模型还有很多话要说,我们将在第四章《应用模型》中深入介绍。

接下来,我们必须让我们的模块知道这个新的Python文件。这是由__init__.py 文件完成的。由于我们将代码放在models/ 子目录中,我们需要之前的__init__ 文件来导入该目录,该目录又应该包含另一个__init__ 文件,在那里导入每个代码文件(在我们的例子中只有一个)。

通过升级模块激活对Odoo模型的更改。Odoo服务器将处理模型类到数据库结构更改的转换。

虽然这里没有提供示例,但也可以通过向模型的类添加新方法,或者通过扩展现有方法,例如 create()write() ,将业务逻辑添加到这些Python文件中。这将在第五章《基本服务器端开发》中讨论。

添加菜单项目和界面

一旦我们有了满足数据结构需求的模型,我们就需要一个用户界面,以便我们的用户可以与它们进行交互。本节将在上一节的Library Book 模型之上添加了一个菜单项来显示具有列表和表单视图的用户界面。

准备工作

需要上一节中实现的library.book 模型的附加模块。将使用的路径与我们的附加模块位置相关(例如,~/odoo-dev/localaddons/my_library/ )。

实现步骤

要添加视图,我们将在模块中添加一个带有其定义的XML 文件。由于它是一个新模型,我们还必须添加一个菜单选项,以便用户能够访问它。

请注意,以下步骤的顺序是相关的,因为其中一些使用对前面步骤中定义的ID的引用:

  1. 创建XML文件以添加描述用户界面的数据记录,views/library_book.xml

    1
    2
    3
    4
    <?xml version="1.0" encoding="utf-8"?>
    <odoo>
    <!-- Data records go here -->
    </odoo>
  2. 将新数据文件添加到附加模块清单__manifest__.py ,方法是将其添加到views/library_book.xml

    1
    2
    3
    4
    5
    6
    {
    'name': "My Library",
    'summary': "Manage books easily",
    'depends': ['base'],
    'data': ['views/library_book.xml'],
    }
  3. library_book.xml 文件中添加打开视图的操作:

    1
    2
    3
    4
    5
    <record id='library_book_action' model='ir.actions.act_window'>
    <field name="name">Library Books</field>
    <field name="res_model">library.book</field>
    <field name="view_mode">tree,form</field>
    </record>
  4. 将菜单项添加到library_book.xml 文件中,使其对用户可见:

    1
    2
    3
    <menuitem name="My Library" id="library_base_menu" />
    <menuitem name="Books" id="library_book_menu"
    parent="library_base_menu" action="library_book_action"/>
  5. 将自定义表单视图添加到library_book.xml 文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <record id="library_book_view_form" model="ir.ui.view">
    <field name="name">Library Book Form</field>
    <field name="model">library.book</field>
    <field name="arch" type="xml">
    <form>
    <group>
    <group>
    <field name="name"/>
    <field name="author_ids" widget="many2many_tags"/>
    </group>
    <group>
    <field name="date_release"/>
    </group>
    </group>
    </form>
    </field>
    </record>
  6. 将自定义树(列表)视图添加到library_book.xml 文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <record id="library_book_view_tree" model="ir.ui.view">
    <field name="name">Library Book List</field>
    <field name="model">library.book</field>
    <field name="arch" type="xml">
    <tree>
    <field name="name"/>
    <field name="date_release"/>
    </tree>
    </field>
    </record>
  7. 将自定义搜索选项添加到library_book.xml 文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <record id="library_book_view_search" model="ir.ui.view">
    <field name="name">Library Book Search</field>
    <field name="model">library.book</field>
    <field name="arch" type="xml">
    <search>
    <field name="name"/>
    <field name="author_ids"/>
    <filter string="No Authors"
    name="without_author"
    domain="[('author_ids','=',False)]"/>
    </search>
    </field>
    </record>

在Odoo中添加新模型时,用户默认没有任何访问权限。我们必须为新模型定义访问权限才能获得访问权限。在我们的示例中,我们没有定义任何访问权限,因此用户无权访问我们的新模型。如果没有访问权限,我们的菜单和视图也不可见。幸运的是,有一个捷径!通过切换到超级用户模式,您可以在没有访问权限的情况下查看我们应用程序的菜单。

以超级用户身份访问 Odoo

通过将管理员用户转换为超级用户类型,可以绕过访问权限限制,从而访问菜单和视图而无需提供默认访问权限。要将管理员用户转换为超级用户,请激活开发人员模式。完成此操作后,从开发人员工具选项中,单击成为超级用户选项。

以下屏幕截图已作为参考提供:

激活超级用户模式的选项

成为超级用户后,您的菜单将具有条纹背景,如下图所示:

超级用户模式激活

如果您现在尝试升级模块,您应该能够看到一个新的菜单选项(您可能需要刷新您的Web浏览器)。单击 Books 菜单将打开book模型的列表视图,如以下屏幕截图所示:

访问书籍的菜单

运行原理

在底层,用户界面由存储在特殊模型中的记录定义。前两步创建一个空的XML文件来定义要加载的记录,然后将它们添加到模块的要安装的数据文件列表中。

数据文件可以放在模块目录中的任何位置,但惯例是在views/ 子目录中定义用户界面。通常这些文件的名称基于模型的名称。在我们的例子中,我们正在为library.book 模型创建用户界面,因此我们创建了views/library_book.xml 文件。

下一步是定义一个窗口动作以在Web客户端的主区域中显示用户界面。action是一个由res_model 定义的目标模型,name 属性用于在用户打开action时向用户显示标题,这些只是基本属性。窗口操作支持其他属性,可以更好地控制视图的呈现方式,例如要显示哪些视图、在可用记录上添加过滤器或设置默认值。 这些将在第九章《后端视图中》详细讨论。

通常,数据记录是使用<record> 标签定义的,我们在示例中为ir.actions.act_window 模型创建了一条记录。这将创建窗口操作。

同样,菜单项存储在ir.ui.menu 模型中,我们可以使用<record> 标记创建它们。但是在Odoo中有一个名为<menuitem> 的快捷方式标签,因此我们在示例中使用了它。

这些是菜单项的主要属性:

  • name :这是要显示的菜单项文本。
  • action :这是要执行的操作的标识符。我们使用在上一步中创建的窗口操作的ID。
  • sequence :用于设置同级菜单项的显示顺序。
  • parent :这是父菜单项的标识符。我们的示例菜单项没有父项,这意味着它将显示在菜单的顶部。
  • web_icon :此属性用于显示菜单的图标。此图标仅在Odoo企业版中显示。

此时我们还没有在我们的模块中定义任何视图。但是,如果您在此阶段升级您的模块,Odoo将自动动态创建它们。 尽管如此,我们肯定希望控制视图的外观,因此,在接下来的两个步骤中,将创建一个表单和一个树视图。

两个视图都使用ir.ui.view 模型上的记录定义。 我们使用的属性如下:

  • name :这是标识视图的标题。在Odoo的源代码中,您会发现这里重复了XML ID,但如果您愿意,可以添加一个更易读的标题作为名称。

    如果name 字段被省略,Odoo将使用模型名称和视图类型生成一个。这对于新模型的标准视图来说非常好。建议在扩展视图时使用更明确的名称,当您在Odoo的用户界面中查找特定视图时,将变得非常方便。

  • model :这是目标模型的内部标识符,在其_name 属性中定义。

  • arch :这是视图架构,实际定义结构的地方。不同类型的视图都不相同。

表单视图由顶部的<form> 元素定义,其画布是一个双列网格。在表单内部,<group> 元素用于垂直组合字段。两个组产生两个带有字段的列,它们是使用<field> 元素添加的。字段根据其数据类型使用默认小部件,但可以在小部件属性的帮助下使用特定小部件。

树视图更简单;它们由顶部<tree> 元素定义,该元素包含要显示的列的<field> 元素。

最后,我们添加了一个搜索视图以扩展右上角框中的搜索选项。 在<search> 顶级标签内,我们可以有<field><filter> 元素。字段元素是可以从搜索视图中给出的输入中搜索的附加字段。过滤器元素是预定义的过滤条件,可以通过单击激活。这些主题在第九章《后端视图》中详细讨论。

添加访问安全

添加新数据模型时,您需要定义谁可以创建、读取、更新和删除记录。当创建一个全新的应用程序时,这可能涉及定义新的用户组。因此,如果用户没有这些访问权限,那么Odoo将不会显示您的菜单和视图。在上一节中,我们通过将管理员用户转换为超级用户来访问我们的菜单。通过本节,您将能够以管理员用户的身份直接访问我们的库模块的菜单和视图。

本节中建立在前一章节的Library Books之上,并定义了一个新的用户安全组来控制谁可以访问或修改图书记录。

准备工作

需要上一章节使用的library.book 模型的附加模块,我们将为它添加安全规则。使用的路径与我们的附加模块位置相关(例如,~/odoo-dev/local-addons/my_library/ )。

实现步骤

在本小节中我们要添加的安全规则如下:

  • 每个人都可以阅读图书馆的图书记录。
  • 新建具有权创建、读取、更新和删除图书记录的安全组:Librarians

要实现这一点,您需要执行以下步骤:

  1. 创建一个名为security/groups.xml 的文件,其内容如下:

    1
    2
    3
    4
    5
    6
    7
    <?xml version="1.0" encoding="utf-8"?>
    <odoo>
    <record id="group_librarian" model="res.groups">
    <field name="name">Librarians</field>
    <field name="users" eval="[(4, ref('base.user_admin'))]"/>
    </record>
    </odoo>
  2. 创建名为security/ir.model.access.csv 文件,其内容如下:

    1
    2
    3
    id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
    acl_book,library.book_default,model_library_book,,1,0,0,0
    acl_book_librarian,library.book_librarian,model_library_book,group_librarian,1,1,1,1
  3. 将以上两个文件添加到__manifest__.py 文件的data 条目中:

    1
    2
    3
    4
    5
    6
    7
    # ...
    'data': [
    'security/groups.xml',
    'security/ir.model.access.csv',
    'views/library_book.xml'
    ],
    # ...

更新实例中的插件后,新定义的安全规则将生效。

运行原理

我们提供了两个新的数据文件,将它们添加到附加模块的清单中,以便安装或更新模块会将它们加载到数据库中:

  • security/groups.xml 文件通过创建res.groups 记录来定义新的安全组。我们还通过使用其参考ID base.user_adminLibrarians 的权限授予admin 用户,这样admin用户将拥有library.book 模型的权限。
  • ir.model.access.csv 文件将模型的权限与组相关联。第一行有一个空的group_id:id 列,这意味着该规则适用于所有人。最后一行将所有权限授予我们刚刚创建的组的成员。

清单文件中的的数据部分文件的顺序很重要。创建安全组的文件必须在列出访问权限的文件之前加载,因为访问权限的定义取决于组的存在。由于视图可以特定于安全组,我们建议将组的定义文件放在列表中以更安全。

也可以看看
本书有一章专门介绍安全性。有关安全性的更多信息,请参阅第十章《安全访问》。

使用scaffold命令创建一个模块

创建新的Odoo模块时,需要设置一些样板代码。为了帮助快速启动新模块,Odoo提供了脚手架(scaffold )命令。

本节向你展示了如何使用脚手架命令创建一个新模块,它将生成一个模块需要的文件目录。

准备工作

我们将在自定义模块目录中创建新的附加模块,因此我们需要安装Odoo和自定义模块的目录。假设 Odoo安装在~/odoo-dev/odoo 并且我们的自定义模块放置在~/odoo-dev/local-addons 目录中。

实现步骤

我们将使用scaffold 命令来创建模板代码。执行以下步骤以使用scaffold 命令创建新模块:

  1. 将工作目录更改为我们希望模块所在的位置。这可以是您选择的任何目录,但它必须位于附加路径中才能有用。 按照我们在上面中使用的目录选择,应该如下所示:

    1
    cd ~/odoo-dev/local-addons
  2. 为新模块选择一个技术名称,并使用scaffold 命令创建它。对于我们的示例,我们将选择my_module

    1
    ~/odoo-dev/odoo/odoo-bin scaffold my_module
  3. 编辑提供的__manifest__.py 默认模块清单并更改相关值。您肯定希望至少更改name 键中的模块标题。

这是生成的附加模块应如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
tree my_module
my_module/
├── controllers
│ ├── controllers.py
│ └── __init__.py
├── demo
│ └── demo.xml
├── __init__.py
├── __manifest__.py
├── models
│ ├── __init__.py
│ └── models.py
├── security
│ └── ir.model.access.csv
└── views
├── templates.xml
└── views.xml

5 directories, 10 files

您现在应该编辑各种生成的文件并使它们适应新模块的用途。

运行原理

scaffold 命令可使用模板来创建新模块的结构框架。

默认情况下,新模块是在当前工作目录中创建的,但我们可以提供一个特定的目录来创建模块,将其作为附加参数传递。

类似以下示例:

1
~/odoo-dev/odoo/odoo-bin scaffold my_module ~/odoo-dev/local-addons

使用default 模板,但theme 模板也可用于网站主题创作。要选择特定模板,可以使用-t 选项。 我们还可以使用带有模板的目录的路径。

这意味着我们可以通过scaffold 命令使用我们自己的模板。 内置模板可以在/odoo/cli/templates 的子目录中找到。要使用我们自己的模板,我们可以使用类似以下命令:

1
~/odoo-dev/odoo/odoo-bin scaffold -t path/to/template my_module

默认情况下,Odoo在/odoo/cli/templates 目录中有两个模板。一是default 模板,二是theme 模板。 但是,您可以创建自己的模板或将其与-t 一起使用,如前面的命令所示。

Odoo14开发者指南第三章-创建Odoo附加模块【翻译】

https://www.junle.org/Odoo14开发者指南第三章-创建Odoo附加模块【翻译】/

作者

Junle

发布于

2021-04-02

更新于

2024-03-22

许可协议

评论