这里说的动态网页,是指页面上的数据来自后台。比如:某企业会在网站上发布公告或企业新闻。在页面上一般会创建最新公告或者最新动态的选项卡。这里就拿最新公告来说,在最新公告的选项卡里,可能会显示5条最新的公告,这些公告由后台编辑发布。每当用户进入页面,看到的永远是最新的5条公告。
那么,如何实现呢?
一是创建一个网页页面(website.page)记录,这种方式在安装所在的模块时,会自动添加到导航栏中,在管理员的编辑模式下可以从导航栏取消,或者重新放置到导航栏。
二是创建一个 template ,去继承已有的 template ,并重写已有模板使用的controller,为controller增加返回值,以便在新建template 中使用返回数据。
实际上,第一种方式是在创建一个页面 ,在页面中使用template 。第二种是 继承已有页面,重写原有接口增加返回值。本文只对第一种情况举例说明。
要实现数据的动态展示,一定离不开使用路由(也就是调用接口)。在进入页面后,通过路由获取数据,返回到template 进行数据渲染。下面举例说明:
第一步,创建一条 website.page 的记录,新建文件 /views/zerone_newest_books_pages.xml:
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="newest_books_page" model="website.page">
<field name="name">新上图书</field>
<field name="website_published">True</field>
<field name="url">/newest_book</field>
<field name="type">qweb</field>
<field name="key">zerone_inherit.books_page</field>
<field name="arch" type="xml">
<t t-name="zerone_inherit.newest_books_page_template">
<t t-call="website.layout">
<div class="container">
<div id="wrap">
<div class="row">
<!-- 留位置渲染图书卡片 -->
</div>
</div>
</div>
</t>
</t>
</field>
</record>
<record id="newest_books_page_link" model="website.menu">
<field name="name">Newest Books</field>
<field name="page_id" ref="newest_books_page"/>
<field name="parent_id" ref="website.main_menu"/>
<field name="sequence" type="int">99</field>
</record>
</odoo>
在manifest文件的data中引用上面的xml文件
第二步,创建接口,新建文件 /controllers/newest_books_controller.py
from odoo import http
class NewestBooksController(http.Controller):
@http.route('/newest_book', auth='public', website=True)
def newest_book(self):
book_obj = http.request.env['zerone.book'].sudo()
# 这里的模板是 record: key = zerone_inherit.books_page
return http.request.render('zerone_inherit.books_page', {
'books': book_obj.search([], limit=5, order='id desc')
})
在controllers文件夹下引用上面的文件,并在根部录下的init文件中,引用controllers。
安装或升级,进入网站主页可以看到,菜单栏上多出一个名为Newest Books 的菜单,点击进去啥也没有,是因为传入的books参数还没有拿去渲染。
第三步,创建渲染图书卡片模板,新建文件 /static/src/xml/newest_books_templates.xml
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<template id="book_card">
<t t-name="book_card_template">
<t t-foreach="books" t-as="book">
<div class="col-sm-12 col-md-4 col-lg-4">
<div class="zerone_panel panel-warning">
<h5>
<t t-esc="book.name"/>
</h5>
<span>
<t t-esc="book.author"/>
</span>
</div>
</div>
</t>
</t>
</template>
</odoo>
将上面的文件在 manifest 文件的 data 中引用,并在第一步的文件中,调用此模板:
<div class="row">
<!-- 留位置渲染图书卡片 -->
<t t-call="zerone_inherit.book_card"/>
</div>
第四步,为模板元素增加样式,新建文件 /static/src/css/page_books.css
.zerone_panel {
min-height: 100px;
width: 100%;
padding: 24px !important;
margin: 6px 0;
color: #FFFFFF;
text-align: center;
font-size:14px;
cursor: pointer;
}
.zerone_panel:hover {
background: #666666;
color:#FFFFFF;
}
.panel-warning {
background: #da542e;
}
第五步,引用样式表,新建文件 /views/assets.xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="assets_frontend" name="Page Books Assets" inherit_id="web.assets_frontend">
<xpath expr="." position="inside">
<link rel="stylesheet" href="/zerone_inherit/static/src/css/page_books.css"/>
</xpath>
</template>
</odoo>
再次安装或升级,进入网站主页,可以看到效果
第二种方式,实际上是对继承的使用,这里不做说明,需要看视图继承的请移步 odoo创建新模板及继承已有模板
本文实现的情况是在一个单独的页面中,显示最新的书籍信息,所以创建了一个page页面,若要在已有页面上显示最新书籍信息,则需要继承已有模板,而无需创建新的页面。本文实现过程中,需要注意一下几点:
在第一步中,需要注意
- 页面存放的模型是website.page,可以看出页面是依赖website的,故在manifest文件的depends中应依赖website模块。
- 页面的创建 website_published 表示是否在网站中发布,为True则发布显示,为False则不发布不显示。
- 页面的创建 view_type 是qweb
- 页面的创建 url 既是打开页面的地址,也是下面controller 的接口名
- 页面的创建 key 是当前页面模板的唯一标识,在controller接口返回时会用到,告诉系统渲染哪一个模板
- 页面创建之后,需要创建一个菜单,其存放模型是 website.menu
- 菜单的创建 page_id 是为菜单指定页面
- 菜单的创建 parent_id 是为菜单指定菜单位置
在第二步中,需要注意
- 路由上需要增加一个属性 website = True ,会在请求对象上设置一些新变量,并允许在我们的模板中使用网站布局
- 路由即为第一步中的url
- 返回值中的第一个参数即为第一步中的key,指明渲染模板
在第三步中,需要注意
- template 的 id 就是在第一步中,t-call 调用的模板标识,调用时记得格式:模块名.template的id