Thêm button cho form view trong Odoo
Tut 18: Button @ form view
Odoo Tut 18: Button @ form view
Trước khi xem bài viết này, bạn vui lòng hoàn thành hướng dẫn ở Tut 14: Search, Filter, Group By trong Odoo để tiếp tục tutorial tích hợp thêm button cho form view trong Odoo.
Bài viết này sẽ hướng dẫn bạn:
- Cách thêm mới một nút nhấn (button) giao diện biểu mẫu (form) trong Odoo.
- Các vị trí button thường đặt trong form view:
- Button đặt ở header để thay đổi trạng thái
- Button đặt ở đầu sheet để thống kê thông tin
- Button đặt như một trường trong biểu mẫu (trường hợp này ít dùng)
- Cách hiện thực hành động thực thi tương ứng cho các button này.
Code mẫu hoàn chỉnh việc thêm button vào form view trong Odoo bạn có thể tải về ở cuối bài viết
Môi trường lập trình:
- Ubuntu
- Python 3
- Odoo 13 (released 2019)
Tham khảo bài viết sau để dựng môi trường lập trình Odoo: Tut 2: Hướng dẫn cài đặt Odoo
Thêm button vào form view
Button#1. Thêm các button vào header
Vị trí button ở header của form view thường cho phép user thay đổi trạng thái (state) của record. Đối với vị trí này ta bổ sung thêm tag "header" vào trong thẻ "form" và trước thẻ "sheet".
Trong bối cảnh module quản lý thú cưng của chúng ta, Minh sẽ hiện thực nút bán thú :))) … thực ra đơn giản là cập nhật trạng thái thú cưng đã bán, và thêm 1 button khác để đảo ngược trạng thái đã bán thú là "In Store" để thể hiện thú cưng vẫn còn trong cửa hàng => đây cũng sẽ là trạng thái mặc định khi tạo một "record" thú cưng mới.
addons/mypet/views/my_pet_views.xml
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<record id="my_pet_form_view" model="ir.ui.view">
<field name="name">my.pet.form.view</field>
<field name="model">my.pet</field>
<field name="arch" type="xml">
<form>
<!-- Thêm đoạn block header này vào để được Button#1 -->
<header>
<button name="btn_sell_pet" type="object"
string="Sell Pet" class="oe_highlight"
attrs="{'invisible': [('state', '=', 'sold')]}"/>
<button name="btn_in_store" type="object"
string="In Store" class="oe_default"
attrs="{'invisible': [('state', '=', 'in_store')]}"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<!-- ... -->
</sheet>
</form>
</field>
</record>
</data>
</odoo>
2. Thêm button để thể hiện thông tin (button box)
Nút bấm này thường để hiển thị nhanh thông tin (ví dụ: sản phẩm này đã bán bao nhiêu cái, và khi click vào nút thông tin này nó sẽ hiện ra danh sách đơn hàng của sản phẩm đang xem).
addons/mypet/views/my_pet_views.xml
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<record id="my_pet_form_view" model="ir.ui.view">
<field name="name">my.pet.form.view</field>
<field name="model">my.pet</field>
<field name="arch" type="xml">
<form>
<header>
<!-- ... -->
</header>
<sheet>
<!-- Thêm đoạn block div này vào để được Button#2 -->
<div class="oe_button_box" name="button_box">
<button type="object" name="action_owner_stat" class="oe_stat_button" icon="fa-book">
<field name="number_pets" string="Num Pets" widget="statinfo"/>
</button>
</div>
<!-- ... -->
</sheet>
</form>
</field>
</record>
</data>
</odoo>
3. Thêm button vào giữa form để thực hiện một hành động
Cái này Minh không cũng không biết phải mô tả sao cho phù hợp, nhưng đại loại là thêm một button vào để cho người dùng bấm, và khi bấm vào sẽ thực thi một hành động nào đó mình tự customize như cập nhật form chẳng hạn.
addons/mypet/views/my_pet_views.xml
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<record id="my_pet_form_view" model="ir.ui.view">
<field name="name">my.pet.form.view</field>
<field name="model">my.pet</field>
<field name="arch" type="xml">
<form>
<header>
<!-- ... -->
</header>
<sheet>
<!-- ... -->
<group name="images">
<group>
<!-- ... -->
</group>
<group>
<field name="dob"/>
<field name="gender"/>
<!-- Ta thêm Button#3 ở đây nè, dưới trường Gender, thực ra muốn đặt ở đâu là ta đặt -->
<button name="btn_set_default_values" type="object" string="Set default values" class="oe_highlight"/>
</group>
</group>
<!-- ... -->
</sheet>
</form>
</field>
</record>
</data>
</odoo>
Hiện thực hành động của các button trong model
Ta sẽ hiện thực "logic" của button sẽ hành động làm gì bằng cách định nghĩa phương thức trong model. Tên của phương thức trong model chính là giá trị của trường "name" đã khai báo button trong form file .xml nêu trên.
Như vậy, ta sẽ cần hiện thực các phương thức btn_sell_pet(), btn_in_store(), action_owner_stat(), btn_set_default_values() trong model "my.pet".
- btn_sell_pet(): set trạng thái qua 'sold' (đã bán thú);
- btn_in_store(): set trạng thái qua 'in_store' (thú còn trong cửa hàng);
- action_owner_stat(): trả về action list view lọc với "domain" là theo "Owner" hiện tại;
- btn_set_default_values(): thiết lập các giá trị mặc định cho các trường.
Đợt bổ sung button này ta sẽ thay đổi trạng thái của record, do đó, ta cũng bổ sung thêm field "state" (xem code bên dưới); Và trường thông tin "num_pets" sẽ được tính toán để thể hiện số lượng pet sở hữu bởi owner => nên ta cũng sẽ khai báo field "num_pets" và hiện thực hàm computed tương ứng.
addons/mypet/models/my_pet.py
# -*- coding: utf-8 -*-
from odoo import api, fields, models, tools, _
from odoo.exceptions import UserError, ValidationError
from odoo.http import request
import logging
_logger = logging.getLogger(__name__)
class MyPet(models.Model):
_name = "my.pet"
_description = "My pet model"
# ... cac field khac da hien thuc truoc do ...
state = fields.Selection([
('in_store', 'In Store'),
('sold', 'Sold')
], string='State', default='in_store')
number_pets = fields.Integer(string='Number of pets owned by Owner', compute='_compute_number_pets')
def _compute_number_pets(self):
for record in self:
if record.owner_id:
pets = self.search([('owner_id', '=', record.owner_id.id)])
if pets:
record.number_pets = len(pets)
else:
record.number_pets = 0
else:
record.number_pets = 0
pass
# ... cac phuong thuc khac da hien thuc truoc do ...
# ... them vao cuoi ...
def btn_sell_pet(self):
self.state = 'sold'
pass
def btn_in_store(self):
self.state = 'in_store'
pass
def action_owner_stat(self):
self.ensure_one()
action = self.env.ref('mypet.action_my_pet').read()[0]
action.update({
'domain': [('owner_id', '=', self.owner_id.id)],
})
return action
def btn_set_default_values(self):
self.write({
'name': 'Kitty Cat',
'basic_price': 450000,
'age': 2,
'weight': 5.3,
'gender': 'male',
})
pass
Cập nhật vào Odoo
Sau khi hiện thực view và model, ta tiến hành restart Odoo và update addon "My pet - minhng.info" (aka. "mypet").
Nhấn nút các nút button để kiểm tra logic đã chạy ổn.
Code Download
Code mẫu hoàn chỉnh Tut 18: mypet_250423.zip
Hãy tham gia group Facebook để trao đổi và học hỏi thêm về Odoo nhé các bạn => Khám phá Odoo: https://facebook.com/groups/odoo-dev
- Khóa học lập trình Odoo TP.HCM: Thông tin và đăng ký khóa học
- Khảo sát nhu cầu học nghiệp vụ Odoo Offline @ HCM & đăng ký sớm: https://forms.gle/auBXLNbfuNqhJSbj8
Cài đặt Odoo:
- Docker Compose for Odoo 10
- Docker Compose for Odoo 11
- Docker Compose for Odoo 12
- Docker Compose for Odoo 13
- Docker Compose for Odoo 14
- Docker Compose for Odoo 15
- Docker Compose for Odoo 16
- Docker Compose for Odoo 17
- Docker Compose for Odoo 18
Danh sách bài viết series Odoo:
- Tut 0: Học lập trình Odoo - tutorials
- Tut 1: Odoo là gì?
- Tut 2: Hướng dẫn cài đặt Odoo version 10, 11, 12, 13, 14, 15, 16, 17, 18
- Tut 3: Tạo model trong Odoo
- Tut 4: View trong Odoo
- Tut 5: Controller trong Odoo
- Tut 6: Thừa kế model trong Odoo
- Tut 7: Thừa kế view trong Odoo
- Tut 8: Thừa kế controller trong Odoo
- Tut 9: API trong Odoo - XML-RPC
- Tut 10: Hiện thực wizard trong Odoo
- Tut 11: Tạo widget trong Odoo
- Tut 12: Tạo settings trong Odoo cho custom addon
- Tut 13: Thêm button cho list/tree view trong Odoo
- Tut 14: Search, Filter, Group By trong Odoo
- Tut 15: Kết nối PostgreSQL database của Odoo bằng câu lệnh
- Tut 16: Kết nối pgAdmin vào PostgreSQL database của Odoo
- Tut 17: Tra cứu mã nguồn để lập trình Odoo
Tham gia ngay group trên Facebook để cùng thảo luận với đồng bọn nhé:
- Fanpage Minh: https://www.facebook.com/minhng.info
- Khám phá Odoo: https://www.facebook.com/groups/odoo-dev
Khám phá Odoo