Chương 12: Kế Thừa¶
Một khía cạnh mạnh mẽ của SoOn là tính mô-đun của nó. Một mô-đun được dành riêng cho nhu cầu kinh doanh nhưng các mô-đun cũng có thể tương tác với nhau. Điều này rất hữu ích cho việc mở rộng chức năng của một mô-đun hiện có. Ví dụ: trong kịch bản bất động sản của chúng tôi, chúng tôi muốn hiển thị trực tiếp danh sách tài sản của nhân viên bán hàng trong chế độ xem thông thường của người dùng.
Nhưng trước khi thực hiện kế thừa mô-đun SoOn cụ thể, hãy xem cách chúng ta có thể thay đổi hành vi của các phương thức CRUD (Tạo, Truy xuất, Cập nhật hoặc Xóa) tiêu chuẩn.
Kế thừa Python¶
Ghi chú
Mục tiêu: ở cuối phần này:
Không thể xóa thuộc tính không mới hoặc không bị hủy.

Khi một đề nghị được tạo, trạng thái thuộc tính sẽ thay đổi thành 'Đã nhận được đề nghị'
Không thể tạo ưu đãi với mức giá thấp hơn ưu đãi hiện tại

Trong mô-đun bất động sản của chúng tôi, chúng tôi chưa bao giờ phải phát triển bất kỳ điều gì cụ thể để có thể thực hiện các hành động CRUD tiêu chuẩn. Khung SoOn cung cấp các công cụ cần thiết để thực hiện chúng. Trên thực tế, những hành động như vậy đã được đưa vào mô hình của chúng tôi nhờ tính kế thừa Python cổ điển:
from odoo import fields, models
class TestModel(models.Model):
_name = "test_model"
_description = "Test Model"
...
class TestModel
của chúng ta kế thừa từ Model
cung cấp create()
, read()
, write()
và unlink()
.
Các phương thức này (và bất kỳ phương thức nào khác được xác định trên Model
) có thể được mở rộng để thêm logic nghiệp vụ cụ thể:
from odoo import fields, models
class TestModel(models.Model):
_name = "test_model"
_description = "Test Model"
...
@api.model
def create(self, vals):
# Do some business logic, modify vals...
...
# Then call super to execute the parent method
return super().create(vals)
Trình trang trí model()
là cần thiết cho phương thức create()
vì nội dung của tập bản ghi self
không liên quan trong bối cảnh tạo , nhưng nó không cần thiết đối với các phương pháp CRUD khác.
Điều quan trọng cần lưu ý là mặc dù chúng ta có thể ghi đè trực tiếp phương thức unlink()
, nhưng hầu như bạn sẽ luôn muốn viết một phương thức mới bằng trình trang trí ondelete()
thay vào đó. Các phương thức được đánh dấu bằng trình trang trí này sẽ được gọi trong unlink()
và tránh một số vấn đề có thể xảy ra trong quá trình gỡ cài đặt mô-đun của mô hình khi unlink()
được gọi trực tiếp bị ghi đè.
Trong Python 3, super()
tương đương với super(TestModel, self)
. Cái sau có thể cần thiết khi bạn cần gọi phương thức gốc với tập bản ghi đã sửa đổi.
Nguy hiểm
Điều quan trọng là luôn luôn gọi
super()
để tránh làm gián đoạn luồng. Chỉ có một số trường hợp rất cụ thể mà bạn không muốn gọi nó.Đảm bảo luôn trả về dữ liệu nhất quán với phương thức gốc. Ví dụ: nếu phương thức gốc trả về
dict()
, phần ghi đè của bạn cũng phải trả vềdict()
.
Exercise
Thêm logic nghiệp vụ vào các phương thức CRUD.
Ngăn chặn việc xóa thuộc tính nếu trạng thái của thuộc tính đó không phải là 'Mới' hoặc 'Đã hủy'
Mẹo: tạo một phương thức mới với trình trang trí ondelete()
và nhớ rằng self
có thể là một tập bản ghi có nhiều bản ghi.
Khi tạo phiếu mua hàng, hãy đặt trạng thái thuộc tính thành 'Đã nhận phiếu mua hàng'. Đồng thời phát sinh lỗi nếu người dùng cố gắng tạo phiếu mua hàng với số tiền thấp hơn phiếu mua hàng hiện có.
Mẹo: trường property_id
có sẵn trong vals
, nhưng nó là int
. Để khởi tạo một đối tượng estate.property
, hãy sử dụng self.env[model_name].browse(value)
(example)
Kế thừa mô hình¶
Tham khảo: tài liệu liên quan đến chủ đề này có thể được tìm thấy trong Kế thừa và mở rộng.
Trong mô-đun bất động sản của chúng tôi, chúng tôi muốn hiển thị danh sách các tài sản được liên kết trực tiếp với nhân viên bán hàng trong chế độ xem biểu mẫu Cài đặt / Người dùng & Công ty / Người dùng. Để làm điều này, chúng ta cần thêm một trường vào mô hình res.users
và điều chỉnh chế độ xem của nó để hiển thị nó.
SoOn cung cấp hai cơ chế kế thừa để mở rộng mô hình hiện có theo cách mô-đun.
Cơ chế kế thừa đầu tiên cho phép các mô-đun sửa đổi hành vi của mô hình được xác định trong mô-đun khác bằng cách:
thêm các trường vào mô hình,
ghi đè định nghĩa của các trường trong mô hình,
thêm các ràng buộc vào mô hình,
thêm các phương thức vào mô hình,
ghi đè các phương thức hiện có trong mô hình.
Cơ chế kế thừa thứ hai (ủy quyền) cho phép mọi bản ghi của một mô hình được liên kết với bản ghi của mô hình gốc và cung cấp quyền truy cập minh bạch vào các trường của bản ghi gốc này.

Trong SoOn, cơ chế đầu tiên được sử dụng nhiều nhất. Trong trường hợp của chúng tôi, chúng tôi muốn thêm một trường vào mô hình hiện có, có nghĩa là chúng tôi sẽ sử dụng cơ chế đầu tiên. Ví dụ:
from odoo import fields, models
class InheritedModel(models.Model):
_inherit = "inherited.model"
new_field = fields.Char(string="New Field")
Bạn có thể tìm thấy ví dụ thực tế trong đó hai trường được thêm vào mô hình tại đây.
Theo quy ước, mỗi mô hình kế thừa được xác định trong tệp Python của riêng nó. Trong ví dụ của chúng tôi, nó sẽ là models/inherited_model.py
.
Exercise
Thêm một trường vào Người dùng.
Thêm trường sau vào
res.users
:
Cánh đồng |
Kiểu |
---|---|
thuộc tính_id |
One2many nghịch đảo của trường tham chiếu nhân viên bán hàng trong |
Thêm miền vào trường để nó chỉ liệt kê các thuộc tính có sẵn.
Trong phần tiếp theo, hãy thêm trường vào dạng xem và kiểm tra xem mọi thứ có hoạt động tốt không!
Xem kế thừa¶
Tham khảo: tài liệu liên quan đến chủ đề này có thể được tìm thấy trong Di sản.
Ghi chú
Mục tiêu: ở cuối phần này, danh sách các thuộc tính có sẵn được liên kết với nhân viên bán hàng sẽ được hiển thị trong chế độ xem biểu mẫu người dùng của họ

Thay vì sửa đổi các chế độ xem hiện có tại chỗ (bằng cách ghi đè chúng), SoOn cung cấp tính kế thừa chế độ xem trong đó các chế độ xem 'tiện ích mở rộng' con được áp dụng trên các chế độ xem gốc. Các tiện ích mở rộng này có thể thêm và xóa nội dung khỏi chế độ xem chính của chúng.
Chế độ xem tiện ích tham chiếu chế độ xem gốc của nó bằng cách sử dụng trường inherit_id
. Thay vì một chế độ xem duy nhất, trường arch
của nó chứa một số phần tử xpath
chọn và thay đổi nội dung của chế độ xem gốc của chúng:
<record id="inherited_model_view_form" model="ir.ui.view">
<field name="name">inherited.model.form.inherit.test</field>
<field name="model">inherited.model</field>
<field name="inherit_id" ref="inherited.inherited_model_view_form"/>
<field name="arch" type="xml">
<!-- find field description and add the field
new_field after it -->
<xpath expr="//field[@name='description']" position="after">
<field name="new_field"/>
</xpath>
</field>
</record>
expr
Biểu thức XPath chọn một phần tử trong chế độ xem gốc. Phát sinh lỗi nếu nó không khớp với phần tử nào hoặc nhiều hơn một phần tử
vị trí
Thao tác áp dụng cho phần tử đã so khớp:
- `` bên trong``
nối phần thân của
xpath
vào cuối phần tử phù hợpthay thế
thay thế phần tử phù hợp bằng phần thân của
xpath
, thay thế bất kỳ nút$0
nào xuất hiện trong phần thân mới bằng phần tử gốctrước
chèn phần thân của
xpath
làm anh em trước phần tử phù hợpsau
chèn phần thân của
xpaths
làm phần tử anh em sau phần tử đã so khớpthuộc tính
thay đổi các thuộc tính của phần tử phù hợp bằng cách sử dụng các phần tử
attribute
đặc biệt trong phần thânxpath
Khi khớp một phần tử, thuộc tính position
có thể được đặt trực tiếp trên phần tử cần tìm. Cả hai sự kế thừa dưới đây đều có kết quả như nhau.
<xpath expr="//field[@name='description']" position="after">
<field name="idea_ids" />
</xpath>
<field name="description" position="after">
<field name="idea_ids" />
</field>
Bạn có thể tìm thấy ví dụ về tiện ích mở rộng kế thừa chế độ xem tại đây.
Exercise
Thêm các trường vào chế độ xem Người dùng.
Thêm trường property_ids
vào base.view_users_form
trong trang sổ tay mới.
Mẹo: bạn có thể tìm thấy ví dụ về kế thừa chế độ xem của người dùng tại đây.
Kế thừa được sử dụng rộng rãi trong SoOn do khái niệm mô-đun của nó. Đừng ngần ngại đọc tài liệu tương ứng để biết thêm thông tin!
In the next chapter, we will learn how to interact with other modules.