Odoo10教程---模块化一:新建一个模块及基本视图

257 篇文章 9 订阅
31 篇文章 2 订阅

开启/关闭Odoo服务器

Odoo使用客户端/服务器体系结构,客户端是通过RPC访问Odoo 服务器的Web浏览器。

业务逻辑和扩展通常在服务器端执行,尽管支持客户端特征(例如像交互式地图的新数据表示)可以添加到客户端。

为了启动服务器,只需调用shell中的命令Odoo-bin,必要时将完整路径添加到文件中:

odoo-bin

服务器通过从终端点击Ctrl-C两次或杀死相应的OS进程而停止。

建立一个Odoo模块

服务器和客户端扩展都被打包为可选地加载在数据库中的模块。

Odoo模块可以向Odoo系统添加全新的业务逻辑,或者更改和扩展现有业务逻辑:可以创建一个模块来将国家的会计规则添加到Odoo的通用会计支持中,而下一个模块则为公共汽车车队的实时可视化提供支持。

因此,Odoo中的一切都以模块开始和结束。

模块的布局

Odoo模块可以包含多个元素:

业务对象

声明为Python类,这些资源将根据Odoo的配置自动持久

数据文件

XML或CSV文件声明元数据(视图或工作流)、配置数据(模块参数化)、演示数据等

网络控制器

处理来自Web浏览器的请求

静态Web数据

Web界面或网站使用的图像、CSS或JavaScript文件

模块结构

每个模块是模块目录内的目录。模块目录通过--addons-path选项指定。

提示

大多数命令行选项也可以使用配置文件来设置

通过它的清单声明一个Odoo模块。 请参阅有关它的清单文档

一个模块也是一个带有__init__.py文件的Python包,包含模块中各种Python文件的导入指令。

例如,如果模块有一个单独的mymodule.py文件,__init__.py可能包含:

from . import mymodule

Odoo提供了一种帮助建立一个新模块的机制,odoo-bin有一个子命令scaffold来创建一个空模块:

$ odoo-bin scaffold <module name> <where to put it>

该命令为您的模块创建子目录,并自动为模块创建一系列标准文件。它们中的大多数只包含注释代码或XML。大多数这些文件的用法将在本教程中说明。(译者注:在进入从github上下载的odoo根目录后,执行上面的命令,需要在odoo-bin前面使用python命令)

练习

模块创建

使用上面的命令行创建一个空模块Open Academy,并将其安装在Odoo。

  1. 调用命令 odoo-bin scaffold openacademy myaddons。[3]
  2. 将清单文件适应于您的模块。
  3. 别担心其他文件。

openacademy/__manifest__.py

# -*- coding: utf-8 -*-
{
    'name': "Open Academy",

    'summary': """Manage trainings""",

    'description': """
        Open Academy module for managing trainings:
            - training courses
            - training sessions
            - attendees registration
    """,

    'author': "My Company",
    'website': "http://www.yourcompany.com",

    # Categories can be used to filter modules in modules listing
    # Check https://github.com/odoo/odoo/blob/master/odoo/addons/base/module/module_data.xml
    # for the full list
    'category': 'Test',
    'version': '0.1',

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

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

openacademy/__init__.py

# -*- coding: utf-8 -*-
from . import controllers
from . import models

openacademy/controllers.py

# -*- coding: utf-8 -*-
from odoo import http

# class Openacademy(http.Controller):
#     @http.route('/openacademy/openacademy/', auth='public')
#     def index(self, **kw):
#         return "Hello, world"

#     @http.route('/openacademy/openacademy/objects/', auth='public')
#     def list(self, **kw):
#         return http.request.render('openacademy.listing', {
#             'root': '/openacademy/openacademy',
#             'objects': http.request.env['openacademy.openacademy'].search([]),
#         })

#     @http.route('/openacademy/openacademy/objects/<model("openacademy.openacademy"):obj>/', auth='public')
#     def object(self, obj, **kw):
#         return http.request.render('openacademy.object', {
#             'object': obj
#         })

openacademy/demo.xml

<odoo>
    <data>
        <!--  -->
        <!--   <record id="object0" model="openacademy.openacademy"> -->
        <!--     <field name="name">Object 0</field> -->
        <!--   </record> -->
        <!--  -->
        <!--   <record id="object1" model="openacademy.openacademy"> -->
        <!--     <field name="name">Object 1</field> -->
        <!--   </record> -->
        <!--  -->
        <!--   <record id="object2" model="openacademy.openacademy"> -->
        <!--     <field name="name">Object 2</field> -->
        <!--   </record> -->
        <!--  -->
        <!--   <record id="object3" model="openacademy.openacademy"> -->
        <!--     <field name="name">Object 3</field> -->
        <!--   </record> -->
        <!--  -->
        <!--   <record id="object4" model="openacademy.openacademy"> -->
        <!--     <field name="name">Object 4</field> -->
        <!--   </record> -->
        <!--  -->
    </data>
</odoo>

openacademy/models.py

# -*- coding: utf-8 -*-

from odoo import models, fields, api

# class openacademy(models.Model):
#     _name = 'openacademy.openacademy'

#     name = fields.Char()

openacademy/security/ir.model.access.csv

id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
access_openacademy_openacademy,openacademy.openacademy,model_openacademy_openacademy,,1,0,0,0

openacademy/templates.xml

<odoo>
    <data>
        <!-- <template id="listing"> -->
        <!--   <ul> -->
        <!--     <li t-foreach="objects" t-as="object"> -->
        <!--       <a t-attf-href="{{ root }}/objects/{{ object.id }}"> -->
        <!--         <t t-esc="object.display_name"/> -->
        <!--       </a> -->
        <!--     </li> -->
        <!--   </ul> -->
        <!-- </template> -->
        <!-- <template id="object"> -->
        <!--   <h1><t t-esc="object.display_name"/></h1> -->
        <!--   <dl> -->
        <!--     <t t-foreach="object._fields" t-as="field"> -->
        <!--       <dt><t t-esc="field"/></dt> -->
        <!--       <dd><t t-esc="object[field]"/></dd> -->
        <!--     </t> -->
        <!--   </dl> -->
        <!-- </template> -->
    </data>
</odoo>

对象关系映射

Odoo的一个关键组件是ORM层。这一层避免了手工编写大多数SQL并提供可扩展性和安全性服务[2]。

业务对象被声明为扩展了Model的Python类,这些类将它们集成到自动持久化系统中。

模型可以通过在其定义中设置多个属性来配置。最重要的属性是_name,它需要在Odoo系统中定义模型的名称。这里是一个模型的最小完整定义:

from odoo import models
class MinimalModel(models.Model):
    _name = 'test.model'

模型字段

字段用于定义模型可以存储的内容和位置。字段定义为模型类的属性:

from odoo import models, fields

class LessMinimalModel(models.Model):
    _name = 'test.model2'

    name = fields.Char()

共同属性

与模型本身非常相似,可以通过将配置属性作为参数来配置其字段:

name = field.Char(required=True)

某些属性在所有字段都可用,这里是最常见的属性:

string (unicode, 默认的: 字段的name)

UI中字段的标签(用户可见)

required (bool, 默认的False)

如果True,字段不能为空,则它必须具有默认值,或者在创建记录时总是被赋予一个值

help (unicode, 默认的'')

长的表单,为UI中的用户提供帮助工具提示

index (bool, 默认的False)

请求Odoo在列上创建数据库索引

简单字段

字段有两大类:“简单”字段,这些字段是直接存储在模型表中的原子值和链接记录(同一模型或不同模型)的“关系”字段。

简单字段示例是 BooleanDateChar

保留字段

Odoo在所有模型[1]中创建了几个字段。这些字段由系统管理,不应写入。如果有用或必要,它们可以被读取:

id (Id)

模型中记录的唯一标识

create_date (Datetime)

记录的创建日期

create_uid (Many2one)

创建记录的用户

write_date (Datetime)

记录的最后修改日期

write_uid (Many2one)

上次修改记录的用户

特殊字段

默认情况下,Odoo还需要所有模型上的name 字段,这是为了所有显示和搜索行为。用于这些目的的字段可以通过设置_rec_name来重写。

练习

定义一个模型

openacademy 模块中定义一个新的数据模型Course。课程有标题和描述。课程必须有标题。

编辑文件 openacademy/models/models.py 以包含一个Course类。

openacademy/models.py

from odoo import models, fields, api

class Course(models.Model):
    _name = 'openacademy.course'

    name = fields.Char(string="Title", required=True)
    description = fields.Text()

数据文件

Odoo是一个高度数据驱动的系统。虽然使用Python代码定制行为,但模块的值的一部分是在数据中的并在加载时设置。

提示

有些模块只存在于Odoo中添加数据

模块数据是通过数据文件、带有<record>元素的XML文件来声明的。每个<record>元素创建或更新数据库记录

<odoo>
    <data>
        <record model="{model name}" id="{record identifier}">
            <field name="{a field name}">{a value}</field>
        </record>
    </data>
</odoo>
  • model 是记录的Odoo模型的名称
  • id 是一个外部标识符,它允许引用记录(而不必知道它的数据库标识符)
  • <field> 元素具有一个 name ,其是模型中的字段的名称(例如description)。它们的内容是字段的值

数据文件必须在要加载的清单文件中声明,它们可以在'data'列表(总是加载)或'demo'列表中声明(仅加载在演示模式中)。

练习

定义演示数据

创建示范性数据填充带有一些示范课程的Courses 模型。

编辑文件 openacademy/demo/demo.xml 以包含某些数据。

openacademy/demo.xml

<odoo>
    <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>
</odoo>

动作和菜单

动作和菜单是数据库中的常规记录,通常通过数据文件声明。动作可以通过三种方式触发:

  1. 通过点击菜单项 (链接到特定的动作)
  2. 通过单击视图中的按钮 (如果这些连接到动作)
  3. 作为对象的上下文动作

因为菜单有一些复杂的声明,所以有一个<menuitem>快捷方式来声明ir.ui.menu并更容易地将它连接到相应的动作。

<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"/>

危险

必须在XML文件中的相应菜单之前声明该动作。

数据文件按顺序执行,在创建菜单之前,动作id必须存在于数据库中。

练习

定义新的菜单条目

定义新菜单项以访问OpenAcademy 菜单项下的课程。用户应该能够:

  • 显示所有课程的列表
  • 创建/修改课程
  1. 创建带有动作和触发动作的菜单openacademy/views/openacademy.xml
  2. 将其添加到openacademy/__manifest__.pydata 列表中

openacademy/__manifest__.py

    'data': [
        # 'security/ir.model.access.csv',
        'templates.xml',
        'views/openacademy.xml',
    ],
    # only loaded in demonstration mode
    'demo': [

openacademy/views/openacademy.xml

<?xml version="1.0" encoding="UTF-8"?>
<odoo>
    <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>
</odoo>

基本视图

视图定义模型的记录显示方式。每种类型的视图代表可视化的模式(记录列表,它们的聚合图,…)。一般情况下,视图可以通过它们的类型(例如合作伙伴的列表)或具体地通过它们的id来请求。对于通用请求,将使用具有正确类型和最低优先级的视图(因此,每种类型的最低优先级视图是该类型的默认视图)。

视图继承允许更改在别处声明的视图(添加或删除内容)。

通用的视图声明

视图被声明为模型ir.ui.view的记录。视图类型由arch 字段的根元素暗示:

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

危险

视图的内容是XML。

因此,必须将arch 字段声明为正确解析的type="xml"

树视图

树视图,也称为列表视图,以表格形式显示记录。

它们的根元素是<tree>。树视图的最简单形式只列出表中显示的所有字段(每个字段作为列):

<tree string="Idea list">
    <field name="name"/>
    <field name="inventor_id"/>
</tree>

表单视图

表单用于创建和编辑单个记录。

它们的根元素是<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>

练习

使用XML定制表单视图。

为Course对象创建自己的表单视图。显示的数据应该是:课程name和description。

openacademy/views/openacademy.xml

<?xml version="1.0" encoding="UTF-8"?>
<odoo>
    <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",

练习

Notebooks

在Course表单视图中,将描述字段放在选项卡下,这样以后更容易添加其他选项卡,包含附加信息。

修改Course表单视图如下:

openacademy/views/openacademy.xml

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

表单视图还可以使用简单的HTML来进行更灵活的布局:

<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>,它们由定义哪些字段可以被搜索的字段组成:

<search>
    <field name="name"/>
    <field name="inventor_id"/>
</search>

如果模型不存在搜索视图,Odoo生成一个只允许在name 字段上搜索的视图

练习

搜索课程

允许根据他们的标题或他们的描述搜索课程。

openacademy/views/openacademy.xml

            </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",

 

[1] 它可能是disable the automatic creation of some fields

[2] 编写原始SQL查询是可能的,但需要小心,因为它绕过所有的Odoo认证和安全机制

[3] 关于此命令,首先要知道自己使用的python.exe是哪个?如下图

所以新建模块的命令为:E:\odoo-10.0>E:\odoo-10.0\venv\Scripts\python.exe odoo-bin scaffold openacademy
myaddons

 

下一篇:Odoo10教程---模块化二:模型间关系,继承,计算字段等

附上代码地址:https://download.csdn.net/download/mzl87/10386990

 

ps:有翻译不当之处,欢迎留言指正。

原文地址:https://www.odoo.com/documentation/10.0/howtos/backend.html

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值