Chương 3: Các Mô Hình Và Trường Cơ Bản

At the end of the previous chapter, we were able to create an Odoo module. However, at this point it is still an empty shell which doesn't allow us to store any data. In our real estate module, we want to store the information related to the properties (name, description, price, living area...) in a database. The Odoo framework provides tools to facilitate database interactions.

Trước khi tiếp tục bài tập, hãy đảm bảo mô-đun bất động sản đã được cài đặt, tức là nó phải xuất hiện dưới dạng 'Đã cài đặt' trong danh sách Ứng dụng.

Cảnh báo

Không sử dụng các biến toàn cục có thể thay đổi.

Một phiên bản SoOn có thể chạy song song nhiều cơ sở dữ liệu trong cùng một quy trình python. Các mô-đun riêng biệt có thể được cài đặt trên từng cơ sở dữ liệu này, do đó chúng tôi không thể dựa vào các biến toàn cục sẽ được cập nhật tùy thuộc vào các mô-đun đã cài đặt.

Bản đồ quan hệ giữa các đối tượng

Tham khảo: tài liệu liên quan đến chủ đề này có thể được tìm thấy trong API Người mẫu.

Ghi chú

Mục tiêu: ở cuối phần này sẽ tạo bảng estate_property:

$ psql -d rd-demo
rd-demo=# SELECT COUNT(*) FROM estate_property;
count
-------
    0
(1 row)

Thành phần chính của SoOn là lớp ORM. Lớp này tránh phải viết hầu hết SQL theo cách thủ công và cung cấp các dịch vụ bảo mật và mở rộng2.

Các đối tượng kinh doanh được khai báo là các lớp Python mở rộng Model, tích hợp chúng vào hệ thống lưu trữ tự động.

Các mô hình có thể được cấu hình bằng cách đặt các thuộc tính trong định nghĩa của chúng. Thuộc tính quan trọng nhất là _name, thuộc tính bắt buộc và xác định tên cho mô hình trong hệ thống SoOn. Đây là định nghĩa tối thiểu của một mô hình:

from odoo import models

class TestModel(models.Model):
    _name = "test_model"

Định nghĩa này đủ để ORM tạo bảng cơ sở dữ liệu có tên test_model. Theo quy ước, tất cả các mô hình đều nằm trong thư mục models và mỗi mô hình được xác định trong tệp Python riêng.

Hãy xem cách xác định bảng crm_recurring_plan và cách nhập tệp Python tương ứng:

  1. Mô hình được xác định trong tệp crm/models/crm_recurring_plan.py (xem tại đây)

  2. Tệp crm_recurring_plan.py được nhập vào crm/models/__init__.py (xem tại đây)

  3. Thư mục models được nhập vào crm/__init__.py (xem `tại đây <https://github.com/odoo/odoo/blob/e80911aaead031e7523173789e946ac1fd27c7dc/addons/crm/__init__.py#L5> `__)

Exercise

Xác định mô hình bất động sản

Dựa trên ví dụ được đưa ra trong mô-đun CRM, hãy tạo các tệp và thư mục thích hợp cho bảng estate_property.

Khi các tệp được tạo, hãy thêm định nghĩa tối thiểu cho mô hình estate.property.

Mọi sửa đổi tệp Python đều yêu cầu khởi động lại máy chủ SoOn. Khi khởi động lại máy chủ, chúng ta sẽ thêm tham số -d-u:

$ ./odoo-bin --addons-path=addons,../enterprise/,../tutorials/ -d rd-demo -u estate

-u Estate có nghĩa là chúng tôi muốn nâng cấp mô-đun `` Estate``, tức là ORM sẽ áp dụng các thay đổi lược đồ cơ sở dữ liệu. Trong trường hợp này nó tạo ra một bảng mới. -d rd-demo có nghĩa là việc nâng cấp phải được thực hiện trên cơ sở dữ liệu rd-demo. -u phải luôn được sử dụng kết hợp với -d.

Trong quá trình khởi động, bạn sẽ thấy những cảnh báo sau:

...
WARNING rd-demo odoo.models: The model estate.property has no _description
...
WARNING rd-demo odoo.modules.loading: The model estate.property has no access rules, consider adding one...
...

Nếu đúng như vậy thì bạn nên làm tốt! Để chắc chắn, hãy kiểm tra kỹ với psql như được minh họa trong Mục tiêu.

Exercise

Thêm một mô tả.

Thêm _description vào mô hình của bạn để loại bỏ một trong các cảnh báo.

Trường mẫu

Tham khảo: bạn có thể tìm thấy tài liệu liên quan đến chủ đề này trong API Lĩnh vực.

Các trường được sử dụng để xác định những gì mô hình có thể lưu trữ và nơi chúng được lưu trữ. Các trường được định nghĩa là các thuộc tính trong lớp mô hình:

from odoo import fields, models

class TestModel(models.Model):
    _name = "test_model"
    _description = "Test Model"

    name = fields.Char()

Trường nameChar sẽ được biểu diễn dưới dạng unicode Python str và SQL VARCHAR.

Các loại

Ghi chú

Mục tiêu: ở cuối phần này, một số trường cơ bản lẽ ra đã được thêm vào bảng estate_property:

$ psql -d rd-demo

rd-demo=# \d estate_property;
                                            Table "public.estate_property"
    Column       |            Type             | Collation | Nullable |                   Default
--------------------+-----------------------------+-----------+----------+---------------------------------------------
id                 | integer                     |           | not null | nextval('estate_property_id_seq'::regclass)
create_uid         | integer                     |           |          |
create_date        | timestamp without time zone |           |          |
write_uid          | integer                     |           |          |
write_date         | timestamp without time zone |           |          |
name               | character varying           |           |          |
description        | text                        |           |          |
postcode           | character varying           |           |          |
date_availability  | date                        |           |          |
expected_price     | double precision            |           |          |
selling_price      | double precision            |           |          |
bedrooms           | integer                     |           |          |
living_area        | integer                     |           |          |
facades            | integer                     |           |          |
garage             | boolean                     |           |          |
garden             | boolean                     |           |          |
garden_area        | integer                     |           |          |
garden_orientation | character varying           |           |          |
Indexes:
    "estate_property_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "estate_property_create_uid_fkey" FOREIGN KEY (create_uid) REFERENCES res_users(id) ON DELETE SET NULL
    "estate_property_write_uid_fkey" FOREIGN KEY (write_uid) REFERENCES res_users(id) ON DELETE SET NULL

Có hai loại trường chính: trường 'đơn giản', là các giá trị nguyên tử được lưu trữ trực tiếp trong bảng của mô hình và trường 'quan hệ', liên kết các bản ghi (của cùng một mô hình hoặc các mô hình khác nhau).

Các ví dụ về trường đơn giản là Boolean, Float, Char, DateSelection.

Exercise

Thêm các trường cơ bản vào bảng Bất động sản.

Thêm các trường cơ bản sau vào bảng:

Cánh đồng

Kiểu

tên

Char

Sự miêu tả

Chữ

mã bưu điện

Char

ngày_có sẵn

Ngày

Giá cả dự kiến

Trôi nổi

gia ban

Trôi nổi

phòng ngủ

số nguyên

khu vực sống

số nguyên

mặt tiền

số nguyên

ga-ra

Boolean

vườn

Boolean

khu_vườn

số nguyên

vườn_định hướng

Lựa chọn

Trường garden_orientation phải có 4 giá trị có thể có: 'Bắc', 'Nam', 'Đông' và 'Tây'. Danh sách lựa chọn được xác định là danh sách các bộ dữ liệu, hãy xem tại đây để biết ví dụ .

Khi các trường được thêm vào mô hình, hãy khởi động lại máy chủ bằng -u Estate

$ ./odoo-bin --addons-path=addons,../enterprise/,../tutorials/ -d rd-demo -u estate

Kết nối với psql và kiểm tra cấu trúc của bảng estate_property. Bạn sẽ nhận thấy rằng một số trường bổ sung cũng đã được thêm vào bảng. Chúng ta sẽ xem lại chúng sau.

Thuộc tính chung

Ghi chú

Mục tiêu: ở cuối phần này, các cột nameexpected_price không được rỗng trong bảng estate_property:

rd-demo=# \d estate_property;
                                            Table "public.estate_property"
    Column       |            Type             | Collation | Nullable |                   Default
--------------------+-----------------------------+-----------+----------+---------------------------------------------
...
name               | character varying           |           | not null |
...
expected_price     | double precision            |           | not null |
...

Giống như chính mô hình, các trường có thể được định cấu hình bằng cách chuyển các thuộc tính cấu hình dưới dạng tham số

name = fields.Char(required=True)

Một số thuộc tính có sẵn trên tất cả các trường, đây là những thuộc tính phổ biến nhất:

string (str, mặc định: tên trường)

Nhãn của trường trong giao diện người dùng (người dùng có thể nhìn thấy).

required (bool, mặc định: False)

Nếu True, trường không được để trống. Nó phải có giá trị mặc định hoặc luôn được cung cấp một giá trị khi tạo bản ghi.

help (str, mặc định: '')

Cung cấp chú giải công cụ trợ giúp dạng dài cho người dùng trong giao diện người dùng.

index (bool, mặc định: False)

Yêu cầu SoOn tạo chỉ mục cơ sở dữ liệu trên cột.

Exercise

Đặt thuộc tính cho các trường hiện có.

Thêm các thuộc tính sau:

Cánh đồng

Thuộc tính

tên

yêu cầu

Giá cả dự kiến

yêu cầu

Sau khi khởi động lại máy chủ, cả hai trường sẽ không thể rỗng.

Trường tự động

Tham khảo: tài liệu liên quan đến chủ đề này có thể được tìm thấy trong Trường tự động.

Bạn có thể nhận thấy mô hình của mình có một số trường mà bạn chưa bao giờ xác định. SoOn tạo một vài trường trong tất cả các mô hình1. Các trường này do hệ thống quản lý và không thể ghi vào nhưng có thể đọc được nếu hữu ích hoặc cần thiết:

id (Id)

Mã định danh duy nhất cho bản ghi của mô hình.

create_date (Datetime)

Ngày tạo bản ghi.

create_uid (Many2one)

Người dùng đã tạo bản ghi.

write_date (Datetime)

Ngày sửa đổi cuối cùng của bản ghi.

write_uid (Many2one)

Người dùng sửa đổi bản ghi lần cuối.

Now that we have created our first model, let's add some security!

1

có thể vô hiệu hóa việc tự động tạo một số trường

2

Có thể viết các truy vấn SQL thô nhưng cần thận trọng vì điều này bỏ qua tất cả các cơ chế bảo mật và xác thực của SoOn.