Odoo10 开发者文档(2)--建立一个网站

来源:互联网 发布:无线传感器网络 编辑:程序博客网 时间:2024/06/08 12:40

警告
该向导需要Python的基础知识
该向导需要安装好Odoo


创建一个基础模板
在Odoo里,任务是通过创建模块执行的。
模块决定odoo安装的行为,或通过添加新的行为或改变现有的(包括由其他模块添加的行为)。
Odoo的脚手架(scaffold)可以设置一个基本模块。快速启动简单调用:
odoo-bin scaffold Academy Path
这将自动创建Academy模块在Path目录内。目录可以是现有的模块目录,但模块名称必须是目录内唯一的。


一个演示模块
现在我们有课一个可以安装的“完整的”模块了,虽然它什么都没有,我们仍可以安装。
1.开启odoo服务
./odoo-bin –addons-path addons,my-modules
2.访问http://localhost:8069
3.创建一个包括演示数据的新数据库。
4.点击 Settings ‣ Modules ‣ Modules
5.在右上角删除已安装的过滤器并搜索Academy模块。
6.点击Academy模块的安装按钮


到浏览器
Controllers 解释浏览器请求并将数据返回。
添加一个简单的Controllers,确保它是被__init__ .py导入了的(这样Odoo可以找到它):academy/controllers.py

# -*- coding: utf-8 -*-from odoo import httpclass Academy(http.Controller):    @http.route('/academy/academy/', auth='public')    def index(self, **kw):        return "Hello, world"#     @http.route('/academy/academy/objects/', auth='public')#     def list(self, **kw):

关掉odoo服务并重启它。打开页面http://localhost:8069/academy/academy/, 就可以看到你的页面
hello world


模板
在Python中生成HTML不是很好,通常的解决方法是模板(templates),一个使用占位符和显示逻辑的伪文件。Odoo允许任何Python 模板系统,但提供了自己集成了其他功能的qweb模板系统。
创建一个template,确保template文件在__manifest__.py注册l 。并改变controller 使用我们的模板:
academy/controllers.py:

class Academy(http.Controller):    @http.route('/academy/academy/', auth='public')    def index(self, **kw):        return http.request.render('academy.index', {            'teachers': ["Diana Padilla", "Jody Caroll", "Lester Vaughn"],        })#     @http.route('/academy/academy/objects/', auth='public')#     def list(self, **kw):

academy/templates.xml

<odoo>    <data>        <template id="index">            <title>Academy</title>            <t t-foreach="teachers" t-as="teacher">              <p><t t-esc="teacher"/></p>            </t>        </template>        <!-- <template id="object"> -->        <!--   <h1><t t-esc="object.display_name"/></h1> -->        <!--   <dl> -->

这个模板在所有的teachers上重复t-foreach(通过模板上下文),并在自己的分段上打印每个teacher。最后重启Odoo和更新模块的数据(安装模板),在Settings ‣ Modules ‣ Modules ‣ Academy,点击升级。

提示
odoo可以同时重启和更新模板:
odoo-bin --addons-path addons,my-modules -d academy -u academy

访问 http://localhost:8069/academy/academy/ 并将看到:
template


储存数据到odoo
odoo模型(model)映射到数据库表。在上一节中,我们只显示了在Python代码中静态输入的字符串列表。这不允许修改或持久存储,所以我们现在将数据移动到数据库中。

1.定义数据模型
定义一个teacher模型,并导入到__init__.py文件。这样它才能被正确的加载。
academy/models.py:

from odoo import models, fields, apiclass Teachers(models.Model):    _name = 'academy.teachers'    name = fields.Char()

然后为模型设置基本访问控制并将其添加到清单中:
academy/models.py:

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

academy/security/ir.model.access.csv:

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlinkaccess_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0

这只是给所有用户(group_id:id空的)可读访问权限(perm_read

注意
数据文件(XML或CSV)必须添加到模块manifest里面,Python文件(mdel或controllers不然,但必须(直接过间接的)添加到__init__/py
警告
管理员用户可绕开访问权限,即使没有得到权限他们也能访问所有的模型。

2.示范数据
第二步就是添加示范数据到系统中,如此测试起来比较容易。
添加一个demo数据文件,必须链接到manifest:
academy/demo.xml:

<odoo>    <data>        <record id="padilla" model="academy.teachers">            <field name="name">Diana Padilla</field>        </record>        <record id="carroll" model="academy.teachers">            <field name="name">Jody Carroll</field>        </record>        <record id="vaughn" model="academy.teachers">            <field name="name">Lester Vaughn</field>        </record>    </data></odoo>

提示
数据文件能被demo和non-demo数据使用。demo数据只能在demonstration mode(示范模型)中被加载,而且可用于流量测试和演示,非演示数据总是被作为初始系统设置加载和使用。
在这种情况下,我们使用演示数据是因为该系统一个真实的用户会想输入或导入他们自己的teachers名单,这个名单只是用于测试。

3.访问数据
最后一步是改变模型和模板来使用我们的演示数据:
(1)从数据库中获取记录而不是静态列表
(2)因为search()返回一组匹配过滤器的记录 (“all records” here),改变模板使之打印每一个teacher的名字
academy/controllers.py:

class Academy(http.Controller):    @http.route('/academy/academy/', auth='public')    def index(self, **kw):        Teachers = http.request.env['academy.teachers']        return http.request.render('academy.index', {            'teachers': Teachers.search([])        })#     @http.route('/academy/academy/objects/', auth='public')

academy/templates.xml:

        <template id="index">            <title>Academy</title>            <t t-foreach="teachers" t-as="teacher">                <p><t t-esc="teacher.id"/> <t t-esc="teacher.name"/></p>            </t>        </template>        <!-- <template id="object"> -->

重启服务,并更新模块(为了更新manifest和templates以及加载demo文件),然后访问http://localhost:8069/academy/academy/,这个页面应该会有一些不一样:名字前面应该有数字符号(数据库检验了teacher).


网站的支持
odoo绑定一个模块来建立一个网站。
到目前为止,我们已经相当直接地使用了的controllers,但Odoo 8通过website模块更加深化了整合和一些其他的服务(例如,默认的样式、主题)。
1.首先,吧website作为附属添加到academy。
2.然后,添加website=True标识到controller,这将在请求对象上设置一些新变量,并允许在我们的模板中使用website布局
3.在模板布局中使用website布局
academy/__manifest__.py

    'version': '0.1',    # any module necessary for this one to work correctly    'depends': ['website'],    # always loaded    'data': [

academy/controllers.py

from odoo import httpclass Academy(http.Controller):    @http.route('/academy/academy/', auth='public', website=True)    def index(self, **kw):        Teachers = http.request.env['academy.teachers']        return http.request.render('academy.index', {

academy/templates.xml

<odoo>    <data>        <template id="index">            <t t-call="website.layout">                <t t-set="title">Academy</t>                <div class="oe_structure">                    <div class="container">                        <t t-foreach="teachers" t-as="teacher">                            <p><t t-esc="teacher.id"/> <t t-esc="teacher.name"/></p>                        </t>                    </div>                </div>            </t>        </template>        <!-- <template id="object"> -->

老规矩,重启更新后访问http://localhost:8069/academy/academy/ 它应该会产生一个更好的页面,带有品牌和一些内置的页面元素(顶级菜单,页脚,…)
这里写图片描述
网站布局还提供了编辑工具的支持:点击登录(在右上角),填写凭据(默认为admin / admin),然后单击登录,你现在在Odoo“proper”:管理界面。现在点击网站菜单项(左上角)。我们作为一个管理员回到了网站,获得了有网站支持规定的先进的版本功能。
·模板代码编辑器(Customize ‣ HTML Editor),您可以查看和编辑用于当前页的所有模板。
·在左上角编辑按钮切换到“编辑模式”,里面有块(片段)和丰富的文本版本可用
·其他一些功能,如移动预览或SEO(搜索引擎优化 )


URLs和路由
controllers的访问通过 route()修饰器与路由相关联,router()带有一个路由串一些属性来定制它的行为或安全。
我们已经看到了一个“字面意义上”的路由字符串,它完全匹配一个URL部分,但路由字符串也可以使用转换器模式相匹配的URL位,使这些可用作为局部变量。例如,我们可以创建一个新的controller方法,它需要一些URL并把它打印出来:
academy/controllers.py

            'teachers': Teachers.search([])        })    @http.route('/academy/<name>/', auth='public', website=True)    def teacher(self, name):        return '<h1>{}</h1>'.format(name)#     @http.route('/academy/academy/objects/', auth='public')#     def list(self, **kw):#         return http.request.render('academy.listing', {

重启 访问 http://localhost:8069/academy/Alice/ 和 http://localhost:8069/academy/Bob/ 查看不同。
正如名称所示,转换器模式不只是提取,他们也做验证和转换,所以我们可以改变新的controller只接受整数:
academy/controllers.py:

            'teachers': Teachers.search([])        })    @http.route('/academy/<int:id>/', auth='public', website=True)    def teacher(self, id):        return '<h1>{} ({})</h1>'.format(id, type(id).__name__)#     @http.route('/academy/academy/objects/', auth='public')

重启,访问 http://localhost:8069/academy/2 注意,旧的值是一个字符串,但新的被转换成了一个整型,试着访问 http://localhost:8069/academy/Carol/ 注意,这个页面访问不到:因为“Carol”不是一个整型,这个路由被忽略了,而且没有路由能够被访问到。
odoo提供一个叫做model的传统转换器,当被给予id时它直接提供记录。
现在我们用这个来创建一个通用页的教师传记:
academy/controllers.py:

            'teachers': Teachers.search([])        })    @http.route('/academy/<model("academy.teachers"):teacher>/', auth='public', website=True)    def teacher(self, teacher):        return http.request.render('academy.biography', {            'person': teacher        })#     @http.route('/academy/academy/objects/', auth='public')

academy/templates.xml:

                </div>            </t>        </template>        <template id="biography">            <t t-call="website.layout">                <t t-set="title">Academy</t>                <div class="oe_structure"/>                <div class="oe_structure">                    <div class="container">                        <p><t t-esc="person.id"/> <t t-esc="person.name"/></p>                    </div>                </div>                <div class="oe_structure"/>            </t>        </template>        <!-- <template id="object"> -->        <!--   <h1><t t-esc="object.display_name"/></h1> -->        <!--   <dl> -->

然后改变model列表以链接到我们的新controller:
academy/templates.xml

                <div class="oe_structure">                    <div class="container">                        <t t-foreach="teachers" t-as="teacher">                            <p><a t-attf-href="/academy/{{ slug(teacher) }}">                              <t t-esc="teacher.name"/></a>                            </p>                        </t>                    </div>                </div>                <div class="oe_structure"/>                <div class="oe_structure">                    <div class="container">                        <h3><t t-esc="person.name"/></h3>                    </div>                </div>                <div class="oe_structure"/>

重启odoo并更新模块,然后你可以访问每一个teacher的页面,作为一个练习,试着在老师的页面上添加块来写一个传记,然后去另一个老师的页面等等。您会发现,您的传记是所有教师之间共享,因为块被添加到模板,并在所有教师之间共享的传记模板,当一个页面编辑,他们都在同一时间编辑。


文件编辑
记录的具体数据应该保存在记录上,所以我们给老师添加一个新的传记字段:
academy/models.py

    _name = 'academy.teachers'    name = fields.Char()    biography = fields.Html()

academy/templates.xml

                <div class="oe_structure">                    <div class="container">                        <h3><t t-esc="person.name"/></h3>                        <div><t t-esc="person.biography"/></div>                    </div>                </div>                <div class="oe_structure"/>

现在有一个在teacher的名字下占位符的和给在编辑模式中块的一个新区域。这里的内容被保存在相应的teacher的传记文件,从而具体到该teacher。teacher的名字特使可编辑的,保存时,索引页上可见更改 。t-field也可以采取依赖于确切字段的格式选项。例如,如果我们显示教室记录的修改日期:
academy/templates.xml

                <div class="oe_structure">                    <div class="container">                        <h3 t-field="person.name"/>                        <p>Last modified: <i t-field="person.write_date"/></p>                        <div t-field="person.biography"/>                    </div>                </div>

它用一种用非常“电脑化”的方式显示的,并且很难读,但我们可以找一个人类可读的版本:
academy/templates.xml:

                <div class="oe_structure">                    <div class="container">                        <h3 t-field="person.name"/>                        <p>Last modified: <i t-field="person.write_date" t-options='{"format": "long"}'/></p>                        <div t-field="person.biography"/>                    </div>                </div>

或相对应的显示
academy/templates.xml:

                <div class="oe_structure">                    <div class="container">                        <h3 t-field="person.name"/>                        <p>Last modified: <i t-field="person.write_date" t-options='{"widget": "relative"}'/></p>                        <div t-field="person.biography"/>                    </div>                </div>

管理与ERP集成
1.一个Odoo管理简单的且不完全的Odoo管理的介绍
在网站管理部分里能粗略的看到odoo的管理,我们可以在菜单中使用Administrator ‣ Administrator回到那(或者说你如果登出了,登录进去)。
Odoo后端的概念结构很简单:
(1)首先是菜单(Menus),记录的是个树(菜单可以有子菜单)。菜单没有到action的子映射
(2)actions有多种类型:链接(links)、报道(reports),Odoo应执行或数据显示的代码(code)。显示数据的actions被叫做window actions,并告诉odoo根据一组views显示model
(3)view有一个类型,一个它对应的(列表、图表、日历)广泛领域和一种定制模型被显示在view中的方式的结构。
2.在odoo管理中编辑
默认情况下,一个Odoo模型用户是根本看不见的,为了使它可见,它必须在action中有效,这个action它本身是可访问的。通常通过菜单。
给model创建一个菜单
academy/__manifest__.py

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

academy/views.xml

<odoo> <data>  <record id="action_academy_teachers" model="ir.actions.act_window">    <field name="name">Academy teachers</field>    <field name="res_model">academy.teachers</field>  </record>  <menuitem sequence="0" id="menu_academy" name="Academy"/>  <menuitem id="menu_academy_content" parent="menu_academy"            name="Academy Content"/>  <menuitem id="menu_academy_content_teachers"            parent="menu_academy_content"            action="action_academy_teachers"/>

然后访问http://localhost:8069/web/ 左上方有一个默认选择的Academy菜单,它是第一菜单,它作为第一个菜单,并开设了一个teacher名单。从列表中可以创建新的教师记录,并切换到“form”的记录视图。如果没有定义如何显示记录(视图)Odoo将自动创建一个基本的on-the-fly。 在我们的例子中,它为“list”视图工作(只显示老师的名字),但在“form”视图中,HTML传记字段与名称字段并排显示,没有给出足够的空间。现在定义一个自定义窗体视图,以便更好地查看和编辑教师记录:
academy/views.xml

    <field name="name">Academy teachers</field>    <field name="res_model">academy.teachers</field>  </record>  <record id="academy_teacher_form" model="ir.ui.view">    <field name="name">Academy teachers: form</field>    <field name="model">academy.teachers</field>    <field name="arch" type="xml">      <form>        <sheet>          <label for="name"/> <field name="name"/>          <label for="biography"/>          <field name="biography"/>        </sheet>      </form>    </field>  </record>  <menuitem sequence="0" id="menu_academy" name="Academy"/>  <menuitem id="menu_academy_content" parent="menu_academy"

3.模型间关联
我们已经看到了一对直接存储在记录中的“基本”字段。有一些基本字段。第二大类字段是关系型的,用于将记录彼此链接(模型内或模型间)。 为了演示,让我们创建一个课程模型。每个课程都应该有一个教师字段,连接到一个单一的教师记录,但每个教师可以教许多课程:
academy/models.py

    name = fields.Char()    biography = fields.Html()class Courses(models.Model):    _name = 'academy.courses'    name = fields.Char()    teacher_id = fields.Many2one('academy.teachers', string="Teacher")

academy/security/ir.model.access.csv

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlinkaccess_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0access_academy_courses,access_academy_courses,model_academy_courses,,1,0,0,0

现在添加视图,以便我们能看见和编辑课程的教师
academy/views.xml

      </form>    </field>  </record>  <record id="action_academy_courses" model="ir.actions.act_window">    <field name="name">Academy courses</field>    <field name="res_model">academy.courses</field>  </record>  <record id="academy_course_search" model="ir.ui.view">    <field name="name">Academy courses: search</field>    <field name="model">academy.courses</field>    <field name="arch" type="xml">      <search>        <field name="name"/>        <field name="teacher_id"/>      </search>    </field>  </record>  <record id="academy_course_list" model="ir.ui.view">    <field name="name">Academy courses: list</field>    <field name="model">academy.courses</field>    <field name="arch" type="xml">      <tree string="Courses">        <field name="name"/>        <field name="teacher_id"/>      </tree>    </field>  </record>  <record id="academy_course_form" model="ir.ui.view">    <field name="name">Academy courses: form</field>    <field name="model">academy.courses</field>    <field name="arch" type="xml">      <form>        <sheet>          <label for="name"/>          <field name="name"/>          <label for="teacher_id"/>          <field name="teacher_id"/>        </sheet>      </form>    </field>  </record>  <menuitem sequence="0" id="menu_academy" name="Academy"/>  <menuitem id="menu_academy_content" parent="menu_academy"            name="Academy Content"/>  <menuitem id="menu_academy_content_courses"            parent="menu_academy_content"            action="action_academy_courses"/>  <menuitem id="menu_academy_content_teachers"            parent="menu_academy_content"

也应该有可能直接从老师的主页上创建新的课程,或者看到他们所教的所有课程,因此给教师模型增加反向关系
academy/models.py

    name = fields.Char()    biography = fields.Html()    course_ids = fields.One2many('academy.courses', 'teacher_id', string="Courses")class Courses(models.Model):    _name = 'academy.courses'

academy/views.xml

    <field name="arch" type="xml">      <form>        <sheet>          <label for="name"/> <field name="name"/>          <label for="biography"/>          <field name="biography"/>          <field name="course_ids">            <tree string="Courses" editable="bottom">              <field name="name"/>            </tree>          </field>        </sheet>      </form>

4.讨论和通知
Odoo提供技术模型,它不直接满足业务需要反而增加业务对象的能力而不必手动建立。
其中之一是Chatter(聊天)系统,Odoo电子邮件和短信系统的一个部分,可以添加通知和讨论线程到所有的模型。该模型只需_inherit mail.thread,并添加message_ids字段到form视图来显示讨论线程。讨论线程是pre-record。对于我们的academy,让讨论课程来处理例如调度变化或教师和助理之间的讨论是比较有意义的:
academy/models.py

class Courses(models.Model):    _name = 'academy.courses'    _inherit = 'mail.thread'    name = fields.Char()    teacher_id = fields.Many2one('academy.teachers', string="Teacher")

academy/views.xml

          <field name="name"/>          <label for="teacher_id"/>          <field name="teacher_id"/>        </sheet>        <div class="oe_chatter">          <field name="message_follower_ids" widget="mail_followers"/>          <field name="message_ids" widget="mail_thread"/>        </div>      </form>    </field>

在每个课程表单的底部,现在有一个讨论线程和系统用户留言的功能还有是否要follow讨论链接到指定课程。

5.销售课程
odoo还提供了商业模型,它可以更直接的使用或选择商业需求。比如website_sale模块建立了一个基于产品在Odoo系统的电子商务(e-commerce)网站。我们可以很容易地通过我们的课程课程订阅特定种类的产品销售。而不是以前的经典继承,这意味着生成模型更换我们的课程模式,并扩大产品原状(添加我们需要的所有给它)。
首先,我们需要添加website_sale依赖以便我们得到的产品(通过出售)和电子商务接口:
academy/__manifest__.py

    'version': '0.1',    # any module necessary for this one to work correctly    'depends': ['website_sale'],    # always loaded    'data': [

重启服务,更新模块,现在网站中有了一个Shop ,列出很多预填产品(通过演示数据)
academy/__manifest__.py

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

academy/data.xml

<odoo><data>  <record model="product.public.category" id="category_courses">    <field name="name">Courses</field>    <field name="parent_id" ref="website_sale.categ_others"/>  </record></data></odoo>

academy/demo.xml

        <record id="vaughn" model="academy.teachers">            <field name="name">Lester Vaughn</field>        </record>        <record id="course0" model="product.template">            <field name="name">Course 0</field>            <field name="teacher_id" ref="padilla"/>            <field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>            <field name="website_published">True</field>            <field name="list_price" type="float">0</field>            <field name="type">service</field>        </record>        <record id="course1" model="product.template">            <field name="name">Course 1</field>            <field name="teacher_id" ref="padilla"/>            <field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>            <field name="website_published">True</field>            <field name="list_price" type="float">0</field>            <field name="type">service</field>        </record>        <record id="course2" model="product.template">            <field name="name">Course 2</field>            <field name="teacher_id" ref="vaughn"/>            <field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>            <field name="website_published">True</field>            <field name="list_price" type="float">0</field>            <field name="type">service</field>        </record>    </data></odoo>

academy/models.py

    name = fields.Char()    biography = fields.Html()    course_ids = fields.One2many('product.template', 'teacher_id', string="Courses")class Courses(models.Model):    _inherit = 'product.template'    teacher_id = fields.Many2one('academy.teachers', string="Teacher")

academy/security/ir.model.access.csv:

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlinkaccess_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0

academy/views.xml

      </form>    </field>  </record>  <menuitem sequence="0" id="menu_academy" name="Academy"/>  <menuitem id="menu_academy_content" parent="menu_academy"            name="Academy Content"/>  <menuitem id="menu_academy_content_teachers"            parent="menu_academy_content"

这次安装,有一些课程在shop中就可见了,它们能够被搜索到。

注意
· 拓展原模块时,它被inherited没有被赋予新的_name。
· product.template 已经使用了讨论系统,所以我们将它从我们的拓展模型中移除它。
· 我们创建课程是默认为publish,使所以在没有登录的情况下也是可见的。

6.改变现有视图
到此,我们简单的了解:
(1) 新模型的创建
(2) 新视图的创建
(3) 新记录的创建
(4) 对已存在的模型的改变
我们留下了现有记录的变更和现有视图的变更。我们将在商店的页面上实现这两个变更。
视图更改是通过创建扩展视图来实现的,这些视图应用于原始视图的顶部并更改它。这些改动视图可以添加或删除,而不修改原来的,使得它更容易尝试的东西并滚动变化回来。
由于我们的课程是免费的,没有理由显示他们的价格在商店的网页,所以我们要改变视图并隐藏如果是0的价格。第一个任务是找出哪些视图显示价格,这可以通过Customize ‣ HTML Editor 完成,它让我们读到参与渲染一个页面的各种模板。
改变视图需要3步:
(1) 创建一个新视图
(2) 以拓展修图来修改,通过设置新视图的inherit_id到被修改视图的拓展的id。
(3) 在体系结构中,使用XPath标记从修改后的视图中选择和更改元素
academy/templates.xml

                <div class="oe_structure"/>            </t>        </template>        <template id="product_item_hide_no_price" inherit_id="website_sale.products_item">            <xpath expr="//div[hasclass('product_price')]/b" position="attributes">                <attribute name="t-if">product.price &gt; 0</attribute>            </xpath>        </template>        <!-- <template id="object"> -->        <!--   <h1><t t-esc="object.display_name"/></h1> -->        <!--   <dl> -->

第二件事,我们将改变的是使产品类别栏默认可见:Customize ‣ Product Categories让你切换产品类别的树(用于过滤主显示)打开和关闭。
这通过拓展模板的customize_show和active字段完成:一个拓展模板(比如我们刚才创建的)可以是customize_show=True。这个选项将在Customize 用一个检查框显示视图,允许管理员激活或禁用他们(并轻松定制自己的网站页面)。
我们只需要简单的修改Product Categories记录,并设置默认值为active=”True”:
academy/templates.xml

            </xpath>        </template>        <record id="website_sale.products_categories" model="ir.ui.view">            <field name="active" eval="True"/>        </record>        <!-- <template id="object"> -->        <!--   <h1><t t-esc="object.display_name"/></h1> -->        <!--   <dl> -->

这样,Academy 模块被安装的时候,Product Categories栏将自动激活。

0 0