Odoo 开发前台页面和模板引擎的使用
方式一:使用Qweb
带站点基础框的页面
后台代码
@http.route('/trial', auth='public', type='http', website=True)
def trial(self, **kw):
# ...
values = {
'plan': trial_plan,
}
return request.render('saas_portal.try_trial', values)
模板
<template id="try_trial">
<t t-call="website.layout">
<t t-set="title">Try trial</t>
<div class="oe_structure">
<div class="container" style="text-align: center">
<h2>开通: <t t-esc="plan.name"/></h2>
<p>实例正在创建中...</p>
<p>这可能需要几分钟,请稍后在 <a href="/my/home">我的账号</a> 页面 SaaS 栏查看创建的结果</p>
</div>
</div>
</t>
<script>
$(document).ready(function() {
$('div.oe_structure div.container').css('height', $(window).innerHeight());
});
</script>
</template>
- 可以看到模板首先使用了
website.layout
这样页面内容就放置在一个公共的站点基础框内 - Qweb模板引擎使用xml写法,标签大多以 t 开头
- Qweb模板定义的xml文件要加入到模块定义文件的data组下,随模块安装后保存到数据库的视图表ir_ui_view,渲染页面时从数据库读取
完全自定义的页面
后台代码
@http.route('/payment/order_status_show', type='http', auth='public', website=True, methods=['GET'], csrf=False)
def order_status_show(self, **params):
# ...
values = {
'transaction': tx,
'order': order[0].id
}
return request.render("payment.order_status_show", values)
模板
<template id="order_status_show" name="orderstatus" page="True">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta charset="utf-8"/>
<meta http-equiv="pragma" content="no-cache"/>
<meta http-equiv="cache-control" content="no-cache"/>
<meta http-equiv="expires" content="0"/>
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"/>
<title>
订单确认
</title>
<link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/>
<link rel="stylesheet" type="text/css" href="/payment_weixin/static/src/css/qrcode_pay.css"/>
</head>
<body>
<!-- p-header -->
<div class="p-header">
<div class="w">
<div id="logo">
<a href="/"><img width="120" height="40" src="/logo.png" alt="Logo" title="点击返回首页"/></a>
订单确认
</div>
</div>
</div>
<!-- p-header end -->
<div class="main">
<div class="w">
<!-- order 订单信息 -->
<!-- order 订单信息 -->
<div class="order">
<div class="o-left">
<h3 class="o-title">
<t t-esc="'恭喜,您的订单创建成功! 订单号:'+ transaction.reference" />
</h3>
<p class="o-tips">
谢谢光顾,期盼您的
<span class="font-red">
下次
</span>
光临。<a t-attf-href="/my/orders/{{ order }}">查看</a> 订单详细
</p>
</div>
<div class="o-right">
<t t-if="transaction.state == 'done'">
<div class="o-price">
<em>
已付金额
</em>
<strong>
<t t-esc="transaction.amount" />
</strong>
<em>
元
</em>
</div>
</t>
</div>
<div class="clr">
</div>
</div>
<!-- order 订单信息 end -->
<!-- order 订单信息 end -->
<!-- payment 支付方式选择 -->
<div class="payment">
<!-- 微信支付 -->
<div class="pay-weixin">
<div class="p-w-hd">
微信关注我们
</div>
<div class="p-w-bd" style="position:relative">
<div class="p-w-box">
<div class="pw-box-hd">
<img src="http://mall.ziranyidu.com/wx.png" width="298"/>
</div>
<div class="pw-box-ft">
<p>
请使用微信扫一扫
</p>
<p>
扫描二维码关注我们
</p>
</div>
</div>
<div class="p-w-sidebar">
</div>
</div>
</div>
<!-- 微信支付 end -->
</div>
<!-- payment 支付方式选择 end -->
</div>
</div>
</body>
</html>
</template>
方式二:使用Jinja2
以odoo数据库创建页面为例
后台代码
import jinja2
loader = jinja2.PackageLoader('odoo.addons.web', "views")
env = jinja2.Environment(loader=loader, autoescape=True)
class Database(http.Controller):
def _render_template(self, **d):
d.setdefault('manage',True)
d['insecure'] = odoo.tools.config['admin_passwd'] == 'admin'
d['list_db'] = odoo.tools.config['list_db']
d['langs'] = odoo.service.db.exp_list_lang()
d['countries'] = odoo.service.db.exp_list_countries()
# databases list
d['databases'] = []
try:
d['databases'] = http.db_list()
except odoo.exceptions.AccessDenied:
monodb = db_monodb()
if monodb:
d['databases'] = [monodb]
return env.get_template("database_manager.html").render(d)
@http.route('/web/database/manager', type='http', auth="none")
def manager(self, **kw):
return self._render_template(
关键代码return env.get_template("database_manager.html").render(d)
注意这里的 env 和 request.env 没什么关系,不能搞混了
上面的jinja2.PackageLoader('odoo.addons.web', "views")
设置模块引擎从 web 模块的 views 目录下寻找模板文件
模板(节选部分)
<div class="form-group">
<div class="row">
<div class="col-md-12">
<label for="name" class="control-label">Database Name</label>
<input id="name" type="text" name="name" class="form-control" required="required" autocomplete="off"/>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-12">
<label for="login" class="control-label">Email</label>
<input id="login" type="text" name="login" class="form-control" required="required" autocomplete="off"/>
</div>
</div>
</div>
<div class="form-group has-feedback">
<label for="password" class="control-label">Password</label>
<input id="password" type="password" name="password" class="form-control" required="required" autocomplete="off"/>
<span class="fa fa-eye o_little_eye form-control-feedback" aria-hidden="true" style="cursor: pointer; pointer-events: auto"></span>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-6">
<label for="lang" class="control-label">Language</label>
<select id="lang" name="lang" class="form-control" required="required" autocomplete="off">
{% for lang in langs %}
<option {% if lang[0] == "zh_CN" %}selected="selected" {% endif %}value="{{ lang[0] }}">{{ lang[1] }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-6">
<label for="country" class="control-label">Country</label>
<select id="country" name="country_code" class="form-control" autocomplete="off">
<option value=""></option>
{% for country in countries %}
<option {% if country[0] == "cn" %}selected="selected" {% endif %}value="{{ country[0] }}">{{ country[1] }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<input name="demo" type="checkbox" class="pull-right" value="1">
<span>Load demonstration data</span>
<span class="text-muted"> (Check this box to evaluate Odoo)</span>
</label>
</div>
</div>
使用Jinja2引擎的模板文件直接在文件系统里,渲染页面时不需要读数据库,相对快一些,但管理不如Qweb可以直接在线编辑那样方便