form页面添加按钮
一、在xml文件中添加button
<header>
<button name="book_message_btn" string="这是个按钮" type="object" class="btn-primary"/>
</header>
二、在py文件添加按钮方法
1、如果不需要弹窗,直接编写方法内容即可
2、如果需要弹窗
(1)tree弹窗
1)xml文件内容:
<!-- 视图弹窗显示窗口,在页面不显示 -->
<record id="view_tree_book_manager_v" model="ir.ui.view">
<field name="name">book_manager_v</field>
<field name="model">book_manager_v</field>
<field name="arch" type="xml">
<tree delete="0" create="0">
<field name="bookwarehouse"/>
<field name="location"/>
<field name="booknumber"/>
<field name="classify"/>
<field name="status"/>
<field name="bookname"/>
<field name="bookyear"/>
<field name="bookowner"/>
<field name="bookprice"/>
<field name="create_date"/>
</tree>
</field>
</record>
2)py文件内容:
@api.multi
def book_message_btn1(self):
print('1233333')
view_name = 'view_tree_book_manager_v'
view = self.env['ir.model.data'].search([('name', '=', view_name)])
view_id = view.res_id
return {
'name': 'form页面弹窗',
'type': 'ir.actions.act_window',
'view_mode': 'tree',
'view_id': view_id,
'target': 'new',
'res_model': 'book_manager_v',
'res_id': self.id,
'domain': [('id', '=', 1)],
}
3)如果需要对弹窗操作,归根结底是在tree弹窗添加功能按钮,可设置专门的页面添加按钮,以免影响菜单页面的效果
4)效果图:
(2)form弹窗
@api.multi
def book_message_btn(self):
view_name = 'view_form_book_class1'
view = self.env['ir.model.data'].search([('name', '=', view_name)])
view_id = view.res_id
return {
'name': 'form页面弹窗,弹出form',
'type': 'ir.actions.act_window',
'view_mode': 'form',
'view_id': view_id,
'target': 'new',
'res_model': 'book_window',
# 'domain': [()]
}
view_name 可以在xml页面自己定义,确定按钮方法可根据自己需要编写,如果没有,也可不写
@api.multi
def write1(self):
print(self.id)
pass
效果:
(3)无弹窗
@api.multi
def book_message_btn(self):
print('无弹窗')
tree视图添加按钮
一、按钮xml文件
1、在项目中新建文件夹static/src/xml,src下面css、image、scss、js、xml文件夹
2、在xml文件夹下新建所需要按钮的模板,xml文件,内容如下
<templates id="button002" xml:space="preserve">
<t t-extend="ListView.buttons">
<t t-jquery="div.o_list_buttons" t-operation="append">
<t t-if="widget.displayName=='图书档案'">
<button class="btn btn-primary mybutton" type="button">移动图书</button>
</t>
</t>
</t>
</templates>
displayName和menu菜单中目录名称一致,在具体的菜单中展示该按钮,在manifest的data中引入
说明:在odoo15中,如果上述代码不起作用,可以尝试以下代码,
<templates id="mybutton003" xml:space="preserve">
<t t-extend="ListView.buttons" t-name="TestJS.Buttons">
<t t-jquery="button.o_list_button_discard" t-operation="after">
<button class="btn btn-primary mybutton" type="button">测试按钮123</button>
</t>
</t>
</templates>
其中t-name的内容需要在js模板中定义,TestJS和StockIventoryReport是类的名称,如果在继承的类中编写方法,则需要找到最初的父类
3、在manifest的qweb引入上述文件
'qweb': [
'static/src/xml/button1.xml',
]
说明:odoo15引入js和上述文件可以直接在manifest中引入
二、创建按钮位置xml文件并引入
1、在views文件夹下创建mypath.xml,或者其他名字,引入按钮的scss和js文件,内容如下:(若有其他按钮,可在同一文件下编写)
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<template id="assets_backend" inherit_id="web.assets_backend">
<!-- css/scss文件引入位置 -->
<xpath expr="link[last()]" position="after">
<link rel="stylesheet" type="text/scss" href=""/>
</xpath>
<!-- js文件引入位置-->
<xpath expr="script[last()]" position="after">
<script type="text/javascript" src=""></script>
</xpath>
</template>
</odoo>
三、创建按钮js文件,添加按钮事件(按钮css文件可不写)
1、不需要打开新页面
odoo.define('book_manager.book_message_button_group', function (require) {
"use strict";
//这些是调用需要的模块
var ListView = require('web.ListView');
var viewRegistry = require('web.view_registry');
var ListController = require('web.ListController');
//这块代码是继承ListController在原来的基础上进行了扩展
var BookListController = ListController.extend({
renderButtons: function () {
console.log('进入按钮渲染方法');
this._super.apply(this, arguments);
if(this.$buttons){
this.$buttons.find('.mybutton').on('click', this.proxy('book_message_button'));
}
},
book_message_button:function () {
var self = this;
var records = _.map(self.selectedRecords, function (id) {
return self.model.localData[id];
});
var ids = _.pluck(records, 'res_id');
this._rpc({
model: 'book_message',
method: 'book_message_button123', //py文件中按钮方法
args: [ids],
}).then(function(){
self.reload();
});
},
});
// 这块代码是继承ListView在原来的基础上进行扩展
// 这块一般只需要再config中添加上自己的Model, Renderer, Controller
// 这里就对原来的Controller进行了扩展编写,所以就配置了一下BookListController
var BookListView = ListView.extend({
config: _.extend({}, ListView.prototype.config, {
Controller: BookListController,
}),
});
// 这里用来注册编写的视图BookListView,第一个字符串是注册名到时候需要根据注册名调用视图
viewRegistry.add('book_message_button_group', BookListView);
return BookListView;
});
py页面按钮方法:
@api.multi
def book_message_button123(self):
print('移动图书')
print(self.id)
效果:页面刷新,无弹窗弹出
2、点击按钮需要打开新页面进行操作:弹出form
(1)打开form表单,js文件
odoo.define('book_manager.book_message_button_group', function (require) {
"use strict";
//这些是调用需要的模块
var ListView = require('web.ListView');
var viewRegistry = require('web.view_registry');
var ListController = require('web.ListController');
var dialogs = require('web.view_dialogs');
var BookListController = ListController.extend({
renderButtons: function () {
console.log('进入按钮渲染方法');
this._super.apply(this, arguments);
if(this.$buttons){
this.$buttons.find('.mybutton1').on('click', this.proxy('mybutton1'));
}
},
mybutton1:function () {
var self = this;
var records = _.map(self.selectedRecords, function (id) {
return self.model.localData[id];
});
var ids = _.pluck(records, 'res_id');
this._rpc({
model: 'book_message',
method: 'ceshi123', //py文件中按钮方法
args: [ids],
}).then(function(ret){
console.log(ret);
new dialogs.FormViewDialog(self, {
view_id: ret.view_id,
res_id: ret.res_id,
res_model: ret.res_model,
title: '弹窗测试',
custom_close: function () {
self._enableButtons();
self.reload();
},
}).open();
});
},
});
var BookListView = ListView.extend({
config: _.extend({}, ListView.prototype.config, {
Controller: BookListController,
}),
});
// 这里用来注册编写的视图BookListView,第一个字符串是注册名到时候需要根据注册名调用视图
viewRegistry.add('book_message_button_group', BookListView);
return BookListView;
});
(2)method:‘ceshi123’
@api.multi
def ceshi123(self):
view_name = 'view_form_book_message'
view = self.env['ir.model.data'].search([('name', '=', view_name)])
view_id = view.res_id
return {
'title': '选择图书',
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'book_message',
'view_id': view_id,
'target': 'new',
'res_id': self.id,
'flags': {'initial_mode': 'edit'},
}
因为是form页面,所以确定和取消按钮可以在表单中添加,比如上面的write1方法,点击后触发
3、对于上面的write方法可能并不能满足form弹窗后续的方法,下面是点击确定后触发方法
mybutton2:function () {
var self = this;
var records = _.map(self.selectedRecords, function (id) {
return self.model.localData[id];
});
var ids = _.pluck(records, 'res_id');
this._rpc({
model: 'book_message',
method: 'form_window', //py文件中按钮方法
args: [ids],
}).then(function(ret){
new dialogs.FormViewDialog(self, {
view_id: ret.view_id,
res_id: ret.res_id,
res_model: ret.res_model,
title: 'form弹窗',
custom_close: function () {
self._enableButtons();
self.reload();
},
buttons: [
{
text: ret.text || '确定',
classes: 'btn-primary',
close: true,
click: function () {
var dialog_self = this;
var data = dialog_self.form_view.renderer.state.data;
var param = {
res_id: ids,
Fields: data,
};
self._rpc({
model: 'book_window',
method: ret.call_back,
args: [ids,param],
}).then(dialog_self.close.bind(dialog_self))
.always(function () {self._enableButtons();self.reload();});
// console.log(changedFields);
}
}
]
}).open();
});
},
py页面:
# tree页面弹出弹窗,弹窗为form: mybutton2
@api.model
def form_window(self, res_id):
print(res_id)
print('form1')
view_name = 'view_form_book_nofooter'
view = self.env['ir.model.data'].search([('name', '=', view_name)])
view_id = view.res_id
return {
'list_view_id': view_id,
'res_model': 'book_window',
'call_back': 'book_window_callback',
'text': '确定',
}
效果:
book_window_callback方法可根据自己需求编写(在指定的model中编写)
param是js中传入的项目一二三参数
@api.model
def book_window_callback(self, param):
print('sucess123')
print(param)
注意:如果odoo15运行报错: self._rpc(…).then(…).always is not a function,可以尝试在js中修改,如下图
4、点击按钮需要打开新页面进行操作:弹出tree
(1)弹出tree,js文件
odoo.define('book_manager.book_message_button_group', function (require) {
"use strict";
//这些是调用需要的模块
var ListView = require('web.ListView');
var viewRegistry = require('web.view_registry');
var ListController = require('web.ListController');
var dialogs = require('web.view_dialogs');
//这块代码是继承ListController在原来的基础上进行了扩展
var BookListController = ListController.extend({
renderButtons: function () {
console.log('进入按钮渲染方法');
this._super.apply(this, arguments);
if(this.$buttons){
this.$buttons.find('.mybutton').on('click', this.proxy('mybutton1'));
}
},
mybutton1:function () {
var self = this;
var records = _.map(self.selectedRecords, function (id) {
return self.model.localData[id];
});
var ids1 = _.pluck(records, 'res_id');
this._rpc({
model: 'book_message',
method: 'ceshi123', //py文件中按钮方法
args: [ids1],
}).then(function(result){
console.log(result);
new dialogs.SelectCreateDialog(self, {
res_model: 'book_manager_v',
title: '选择货品',
list_view_id: result.list_view_id || false,
search_view_id: result.search_view_id || false,
disable_multiple_selection: false,
no_create: true,
domain: result.domain,
custom_button: true,
text: result.text || '确定',
on_selected: function (records) {
console.log('records', records);
var ids = _.pluck(records, 'res_id');
self._rpc({
model: 'book_message',
method: 'book_window_callback',
args: [ids]
}).then(function (ret) {
console.log('ret', ret);
self.reload();
}
);
}
}).open();
});
},
});
var BookListView = ListView.extend({
config: _.extend({}, ListView.prototype.config, {
Controller: BookListController,
}),
});
viewRegistry.add('book_message_button_group', BookListView);
return BookListView;
});
(2)py文件方法
# tree 页面弹窗,弹出tree:mybutton1
@api.model
def ceshi123(self, res_id):
print(res_id)
print('弹窗测试')
view_id = self.env.ref('book_manager.view_tree_book_manager_v').id
return {
'list_view_id': view_id,
'res_model': 'book_manager_v',
'text': '确定',
}
@api.multi
def book_window_callback(self):
print('success')
(3)效果:
四、在tree视图添加
js_class="book_message_button_group"