Xây dựng một mô-đun¶
Nguy hiểm
This tutorial is outdated. We recommend reading Server framework 101 instead.
Cảnh báo
This tutorial requires having installed Odoo
Bắt đầu/Dừng máy chủ SoOn¶
SoOn sử dụng kiến trúc máy khách/máy chủ trong đó máy khách là trình duyệt web truy cập máy chủ SoOn thông qua RPC.
Logic nghiệp vụ và mở rộng thường được thực hiện ở phía máy chủ, mặc dù các tính năng hỗ trợ máy khách (ví dụ: biểu diễn dữ liệu mới như bản đồ tương tác) có thể được thêm vào máy khách.
Để khởi động máy chủ, chỉ cần gọi lệnh odoo-bin trong shell, thêm đường dẫn đầy đủ vào tệp nếu cần:
odoo-bin
Máy chủ bị dừng bằng cách nhấn Ctrl-C
hai lần từ thiết bị đầu cuối hoặc bằng cách tắt tiến trình hệ điều hành tương ứng.
Xây dựng mô-đun SoOn¶
Cả tiện ích mở rộng máy chủ và máy khách đều được đóng gói dưới dạng mô-đun được tải tùy chọn trong cơ sở dữ liệu.
Các mô-đun SoOn có thể thêm logic kinh doanh hoàn toàn mới vào hệ thống SoOn hoặc thay đổi và mở rộng logic kinh doanh hiện có: một mô-đun có thể được tạo để thêm các quy tắc kế toán của quốc gia bạn vào hỗ trợ kế toán chung của SoOn, trong khi mô-đun tiếp theo bổ sung hỗ trợ cho trực quan hóa thời gian thực của một đội xe buýt.
Do đó, mọi thứ trong SoOn đều bắt đầu và kết thúc bằng các mô-đun.
Thành phần của một mô-đun¶
Một mô-đun SoOn có thể chứa một số thành phần:
- Những đối tượng kinh doanh
Được khai báo là các lớp Python, các tài nguyên này được SoOn tự động lưu giữ dựa trên cấu hình của chúng
- Chế độ xem đối tượng
Định nghĩa hiển thị UI đối tượng kinh doanh
- Tệp dữ liệu
Tệp XML hoặc CSV khai báo siêu dữ liệu mô hình:
dữ liệu cấu hình (tham số mô-đun, quy tắc bảo mật),
dữ liệu trình diễn
và hơn thế nữa
- Bộ điều khiển web
Xử lý các yêu cầu từ trình duyệt web
- Dữ liệu web tĩnh
Hình ảnh, tệp CSS hoặc javascript được sử dụng bởi giao diện web hoặc trang web
Cấu trúc mô-đun¶
Mỗi mô-đun là một thư mục trong một thư mục mô-đun. Các thư mục mô-đun được chỉ định bằng cách sử dụng tùy chọn --addons-path
.
Mẹo
hầu hết các tùy chọn dòng lệnh cũng có thể được đặt bằng cách sử dụng a tệp cấu hình
Một mô-đun SoOn được khai báo bằng manifest.
Một mô-đun cũng là một gói Python với một tệp __init__.py
, chứa các hướng dẫn nhập cho các tệp Python khác nhau trong mô-đun.
Ví dụ: nếu mô-đun có một tệp mymodule.py
duy nhất __init__.py
có thể chứa:
from . import mymodule
SoOn cung cấp một cơ chế giúp thiết lập một mô-đun mới, odoo-bin có một tiểu ban scaffold để tạo một mô-đun trống:
$ odoo-bin scaffold <module name> <where to put it>
Lệnh tạo thư mục con cho mô-đun của bạn và tự động tạo một loạt tệp tiêu chuẩn cho mô-đun. Hầu hết chúng chỉ đơn giản chứa mã nhận xét hoặc XML. Việc sử dụng hầu hết các tệp đó sẽ được giải thích trong hướng dẫn này.
Exercise
Tạo mô-đun
Sử dụng dòng lệnh ở trên để tạo một mô-đun trống Open Academy và cài đặt nó trong SoOn.
Bản đồ quan hệ giữa các đối tượng¶
Một thành phần quan trọng của SoOn là lớp ORM. Lớp này tránh phải viết hầu hết SQL bằng tay và cung cấp các dịch vụ bảo mật và mở rộng2.
Các đối tượng nghiệp vụ đượ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 một số thuộc tính theo đị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 hoàn chỉnh tối thiểu của một mô hình:
from odoo import models
class MinimalModel(models.Model):
_name = 'test.model'
Trường mẫu¶
Các trường được sử dụng để xác định những gì mô hình có thể lưu trữ và ở đâu. Các trường được định nghĩa là các thuộc tính trên lớp mô hình:
from odoo import models, fields
class LessMinimalModel(models.Model):
_name = 'test.model2'
name = fields.Char()
Thuộc tính chung¶
Giống như chính mô hình, các trường của nó 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
(unicode
, 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, trường này 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
(unicode
, mặc định:''
)Dạng dài, cung cấp chú giải công cụ trợ giúp 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.
Các trường đơn giản¶
Có hai loại trường rộng: 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ủa các mô hình khác nhau).
Ví dụ về các trường đơn giản là Boolean
, Date
, Char
.
Các trường dành riêng¶
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 được ghi vào. Chú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 một bản ghi trong mô hình của nó.
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.
Các trường đặc biệt¶
Theo mặc định, SoOn cũng yêu cầu trường tên
trên tất cả các kiểu máy cho các hành vi hiển thị và tìm kiếm khác nhau. Trường được sử dụng cho các mục đích này có thể được ghi đè bằng cách cài đặt _rec_name
.
Exercise
Xác định một mô hình
Xác định mô hình dữ liệu mới Course trong mô-đun openacademy. Một khóa học có tiêu đề và mô tả. Các khóa học phải có tiêu đề.
Hồ sơ dữ liệu¶
SoOn là một hệ thống điều khiển dữ liệu cao. Mặc dù hành vi được tùy chỉnh bằng mã Python, một phần giá trị của mô-đun nằm trong dữ liệu mà nó thiết lập khi được tải.
Mẹo
một số mô-đun tồn tại chỉ để thêm dữ liệu vào SoOn
Dữ liệu mô-đun được khai báo thông qua data files, tệp XML có phần tử <record>
. Mỗi phần tử <record>
tạo hoặc cập nhật một bản ghi cơ sở dữ liệu.
<odoo>
<record model="{model name}" id="{record identifier}">
<field name="{a field name}">{a value}</field>
</record>
</odoo>
model
là tên của mô hình SoOn cho bản ghi.id
là một định danh bên ngoài, nó cho phép tham chiếu đến bản ghi (mà không cần phải biết định danh trong cơ sở dữ liệu của nó).Các phần tử
<field>
cóname
là tên của trường trong mô hình (ví dụ:description
). Phần thân của chúng là giá trị của trường.
Các tệp dữ liệu phải được khai báo trong tệp kê khai cần tải, chúng có thể được khai báo trong danh sách 'data'
(luôn được tải) hoặc trong danh sách 'demo'
(chỉ được tải ở chế độ trình diễn) .
Exercise
Xác định dữ liệu trình diễn
Tạo dữ liệu trình diễn điền vào mô hình Courses với một số khóa học trình diễn.
Mẹo
Nội dung của tệp dữ liệu chỉ được tải khi mô-đun được cài đặt hoặc cập nhật.
Sau khi thực hiện một số thay đổi, đừng quên sử dụng odoo-bin -u openacademy để lưu các thay đổi vào cơ sở dữ liệu của bạn.
Chế độ xem cơ bản¶
Chế độ xem xác định cách hiển thị các bản ghi của mô hình. Mỗi loại chế độ xem đại diện cho một chế độ trực quan hóa (danh sách các bản ghi, biểu đồ tổng hợp của chúng,…). Chế độ xem có thể được yêu cầu một cách chung chung thông qua loại của họ (ví dụ: danh sách đối tác) hoặc cụ thể thông qua id của họ. Đối với các yêu cầu chung, chế độ xem có loại chính xác và mức độ ưu tiên thấp nhất sẽ được sử dụng (vì vậy chế độ xem có mức độ ưu tiên thấp nhất của từng loại là chế độ xem mặc định cho loại đó).
Chế độ xem kế thừa cho phép thay đổi chế độ xem được khai báo ở nơi khác (thêm hoặc xóa nội dung).
Khai báo chế độ xem chung¶
Một view được khai báo là một bản ghi của model ir.ui.view
. Kiểu xem được ngụ ý bởi phần tử gốc của trường arch
:
<record model="ir.ui.view" id="view_id">
<field name="name">view.name</field>
<field name="model">object_name</field>
<field name="priority" eval="16"/>
<field name="arch" type="xml">
<!-- view content: <form>, <tree>, <graph>, ... -->
</field>
</record>
Nguy hiểm
Nội dung của khung nhìn là XML.
Do đó, trường arch
phải được khai báo là type="xml"
để được phân tích cú pháp chính xác.
Chế độ xem cây¶
Chế độ xem dạng cây, còn được gọi là chế độ xem danh sách, hiển thị các bản ghi ở dạng bảng.
Phần tử gốc của chúng là <tree>
. Dạng đơn giản nhất của chế độ xem dạng cây chỉ liệt kê tất cả các trường sẽ hiển thị trong bảng (mỗi trường dưới dạng một cột):
<tree string="Idea list">
<field name="name"/>
<field name="inventor_id"/>
</tree>
Chế độ xem biểu mẫu¶
Các biểu mẫu được sử dụng để tạo và chỉnh sửa các bản ghi đơn lẻ.
Phần tử gốc của chúng là <form>
. Chúng bao gồm các thành phần cấu trúc cấp cao (nhóm, sổ ghi chép) và các thành phần tương tác (nút và trường):
<form string="Idea form">
<group colspan="4">
<group colspan="2" col="2">
<separator string="General stuff" colspan="2"/>
<field name="name"/>
<field name="inventor_id"/>
</group>
<group colspan="2" col="2">
<separator string="Dates" colspan="2"/>
<field name="active"/>
<field name="invent_date" readonly="1"/>
</group>
<notebook colspan="4">
<page string="Description">
<field name="description" nolabel="1"/>
</page>
</notebook>
<field name="state"/>
</group>
</form>
Exercise
Tùy chỉnh chế độ xem biểu mẫu bằng XML
Tạo chế độ xem biểu mẫu của riêng bạn cho đối tượng Khóa học. Dữ liệu hiển thị phải là: tên và mô tả của khóa học.
Exercise
Sổ ghi chép
Trong chế độ xem biểu mẫu Khóa học, hãy đặt trường mô tả dưới một tab để sau này việc thêm các tab khác chứa thông tin bổ sung sẽ dễ dàng hơn.
Chế độ xem biểu mẫu cũng có thể sử dụng HTML đơn giản để có bố cục linh hoạt hơn:
<form string="Idea Form">
<header>
<button string="Confirm" type="object" name="action_confirm"
invisible="state != 'draft'" class="oe_highlight" />
<button string="Mark as done" type="object" name="action_done"
invisible="state != 'confirmed'" class="oe_highlight"/>
<button string="Reset to draft" type="object" name="action_draft"
invisible="state not in ['confirmed', 'done']" />
<field name="state" widget="statusbar"/>
</header>
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Idea Name" />
<h1><field name="name" /></h1>
</div>
<separator string="General" colspan="2" />
<group colspan="2" col="2">
<field name="description" placeholder="Idea description..." />
</group>
</sheet>
</form>
Lượt xem tìm kiếm¶
Chế độ xem tìm kiếm tùy chỉnh trường tìm kiếm được liên kết với chế độ xem danh sách (và các chế độ xem tổng hợp khác). Phần tử gốc của chúng là <search>
và chúng bao gồm các trường xác định trường nào có thể được tìm kiếm trên đó:
<search>
<field name="name"/>
<field name="inventor_id"/>
</search>
Nếu không có chế độ xem tìm kiếm nào cho mô hình, SoOn sẽ tạo một chế độ xem chỉ cho phép tìm kiếm trên trường name
.
Exercise
Tìm kiếm khóa học
Cho phép tìm kiếm các khóa học dựa trên tiêu đề hoặc mô tả của chúng.
Mối quan hệ giữa các mô hình¶
Một bản ghi từ một mô hình có thể liên quan đến một bản ghi từ một mô hình khác. Ví dụ: bản ghi đơn đặt hàng có liên quan đến bản ghi khách hàng chứa dữ liệu khách hàng; nó cũng liên quan đến hồ sơ dòng đơn đặt hàng bán hàng của nó.
Exercise
Tạo mô hình phiên
Đối với mô-đun Học viện Mở, chúng tôi xem xét mô hình cho phiên: phiên là sự xuất hiện của một khóa học được giảng dạy tại một thời điểm nhất định cho một đối tượng nhất định.
Tạo mô hình cho phiên. Một phiên họp có tên, ngày bắt đầu, thời lượng và số ghế. Thêm một hành động và một mục menu để hiển thị chúng. Hiển thị mô hình mới thông qua một mục menu.
Các trường quan hệ¶
Các trường quan hệ liên kết các bản ghi, trong cùng một mô hình (phân cấp) hoặc giữa các mô hình khác nhau.
Các loại trường quan hệ là:
Many2one(other_model, ondelete='set null')
Một liên kết đơn giản đến một đối tượng khác:
print(foo.other_id.name)
Xem thêm
One2many(other_model, liên quan_field)
Một mối quan hệ ảo, nghịch đảo của
Many2one
. AOne2many
hoạt động như một nơi chứa các bản ghi, việc truy cập nó sẽ dẫn đến một tập hợp các bản ghi (có thể trống):for other in foo.other_ids: print(other.name)
Nguy hiểm
Bởi vì
One2many
là một mối quan hệ ảo nên phải có một trườngMany2one
trongother_model
và tên của nó phải làrel_field
Many2many(other_model)
Mối quan hệ đa chiều hai chiều, bất kỳ bản ghi nào ở một bên đều có thể liên quan đến bất kỳ số lượng bản ghi nào ở phía bên kia. Hoạt động như một nơi chứa các bản ghi, việc truy cập nó cũng dẫn đến một tập hợp các bản ghi có thể trống:
for other in foo.other_ids: print(other.name)
Exercise
Quan hệ Many2one
Sử dụng many2one, sửa đổi các mô hình Course và Session để phản ánh mối quan hệ của chúng với các mô hình khác:
Khóa học có người dùng có trách nhiệm; giá trị của trường đó là bản ghi của mô hình tích hợp
res.users
.Một phiên có người hướng dẫn; giá trị của trường đó là bản ghi của mô hình tích hợp
res.partner
.Một phiên có liên quan đến một khóa học; giá trị của trường đó là bản ghi của mô hình
openacademy.course
và là bắt buộc.Điều chỉnh quan điểm.
Exercise
Quan hệ one2man nghịch đảo
Sử dụng trường quan hệ nghịch đảo one2many, sửa đổi các mô hình để phản ánh mối quan hệ giữa các khóa học và phiên học.
Exercise
Nhiều quan hệ many2many
Sử dụng trường quan hệ many2many, sửa đổi mô hình Session để liên kết mọi phiên với một tập hợp người tham dự. Những người tham dự sẽ được đại diện bởi các bản ghi đối tác, vì vậy chúng ta sẽ liên hệ với mô hình tích hợp sẵn res.partner
. Điều chỉnh quan điểm cho phù hợp.
Di sản¶
Kế thừa mô hình¶
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 một mô-đun sửa đổi hành vi của mô hình được xác định trong mô-đun khác:
thêm các trường vào mô hình,
ghi đè định nghĩa của các trường trên mô hình,
thêm các ràng buộc vào một mô hình,
thêm phương thức vào mô hình,
ghi đè các phương thức hiện có trên một mô hình.
Cơ chế kế thừa thứ hai (ủy quyền) cho phép liên kết mọi bản ghi của một mô hình với một bản ghi trong 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.

Xem thêm
_inherit
_inherits
Xem kế thừa¶
Thay vì sửa đổi các chế độ xem hiện tại 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 và có thể thêm hoặc xóa nội dung khỏi chế độ xem gốc của chúng.
Một chế độ xem tiện ích tham chiếu cha mẹ của nó bằng cách sử dụng trường inherit_id
và thay vì một chế độ xem duy nhất, trường arch
của nó bao gồm bất kỳ số phần tử xpath
nào chọn và thay đổi nội dung của chế độ xem cha mẹ của chúng:
<!-- improved idea categories list -->
<record id="idea_category_list2" model="ir.ui.view">
<field name="name">id.category.list2</field>
<field name="model">idea.category</field>
<field name="inherit_id" ref="id_category_list"/>
<field name="arch" type="xml">
<!-- find field description and add the field
idea_ids after it -->
<xpath expr="//field[@name='description']" position="after">
<field name="idea_ids" string="Number of ideas"/>
</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
Mẹo
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 cách thừa kế dưới đây sẽ cho 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>
Exercise
Thay đổi nội dung hiện có
Sử dụng tính kế thừa mô hình, sửa đổi mô hình Partner hiện có để thêm trường boolean
instructor
và trường many2many tương ứng với mối quan hệ phiên-đối tácSử dụng tính kế thừa chế độ xem, hiển thị các trường này trong chế độ xem biểu mẫu đối tác
Tên miền¶
Trong SoOn, Tìm kiếm tên miền là các giá trị mã hóa các điều kiện trên bản ghi. Miền là danh sách các tiêu chí được sử dụng để chọn một tập hợp con các bản ghi của mô hình. Mỗi tiêu chí là một bộ ba có tên trường, toán tử và giá trị.
Ví dụ: khi được sử dụng trên mô hình Sản phẩm, miền sau sẽ chọn tất cả dịch vụ có đơn giá trên 1000:
[('product_type', '=', 'service'), ('unit_price', '>', 1000)]
Theo tiêu chí mặc định được kết hợp với AND ẩn. Các toán tử logic &
(AND), |
(OR) và !
(NOT) có thể được sử dụng để kết hợp các tiêu chí một cách rõ ràng. Chúng được sử dụng ở vị trí tiền tố (toán tử được chèn trước các đối số của nó chứ không phải ở giữa). Ví dụ: để chọn sản phẩm "là dịch vụ HOẶC có đơn giá KHÔNG trong khoảng từ 1000 đến 2000":
['|',
('product_type', '=', 'service'),
'!', '&',
('unit_price', '>=', 1000),
('unit_price', '<', 2000)]
Tham số domain
có thể được thêm vào các trường quan hệ để giới hạn các bản ghi hợp lệ cho mối quan hệ khi cố gắng chọn các bản ghi trong giao diện máy khách.
Exercise
Tên miền trên các trường quan hệ
Khi chọn người hướng dẫn cho một Phiên, chỉ những người hướng dẫn (đối tác có người hướng dẫn
được đặt thành True
) mới được hiển thị.
Exercise
Các miền phức tạp hơn
Tạo các danh mục đối tác mới Giáo viên / Cấp 1 và Giáo viên / Cấp 2. Người hướng dẫn cho một buổi học có thể là người hướng dẫn hoặc giáo viên (ở mọi cấp độ).
Các trường được tính toán và giá trị mặc định¶
Cho đến nay các trường đã được lưu trữ trực tiếp và được lấy trực tiếp từ cơ sở dữ liệu. Các trường cũng có thể được tính toán. Trong trường hợp đó, giá trị của trường không được truy xuất từ cơ sở dữ liệu mà được tính toán nhanh chóng bằng cách gọi một phương thức của mô hình.
Để tạo trường được tính toán, hãy tạo một trường và đặt thuộc tính của nó compute
thành tên của một phương thức. Phương thức tính toán chỉ cần đặt giá trị của trường để tính toán trên mọi bản ghi trong self
.
Nguy hiểm
bản thân
là một bộ sưu tập
Đối tượng self
là một tập bản ghi, tức là một tập hợp các bản ghi được sắp xếp. Nó hỗ trợ các thao tác Python tiêu chuẩn trên các bộ sưu tập, như len(self)
và iter(self)
, cùng với các thao tác tập hợp bổ sung như recs1 + recs2
.
Việc lặp lại self
sẽ cung cấp cho từng bản ghi một, trong đó mỗi bản ghi chính là một tập hợp có kích thước 1. Bạn có thể truy cập/gán các trường trên các bản ghi riêng lẻ bằng cách sử dụng ký hiệu dấu chấm, như record.name
.
import random
from odoo import models, fields, api
class ComputedModel(models.Model):
_name = 'test.computed'
name = fields.Char(compute='_compute_name')
def _compute_name(self):
for record in self:
record.name = str(random.randint(1, 1e6))
phụ thuộc¶
Giá trị của trường được tính toán thường phụ thuộc vào giá trị của các trường khác trên bản ghi được tính toán. ORM yêu cầu nhà phát triển chỉ định các phần phụ thuộc đó vào phương thức tính toán bằng trình trang trí depends()
. ORM sử dụng các phần phụ thuộc đã cho để kích hoạt việc tính toán lại trường bất cứ khi nào một số phần phụ thuộc của nó được sửa đổi:
from odoo import models, fields, api
class ComputedModel(models.Model):
_name = 'test.computed'
name = fields.Char(compute='_compute_name')
value = fields.Integer()
@api.depends('value')
def _compute_name(self):
for record in self:
record.name = "Record with value %s" % record.value
Exercise
Trường tính toán
Thêm phần trăm số ghế đã có vào mô hình Phiên
Hiển thị trường đó trong dạng xem dạng cây và biểu mẫu
Hiển thị trường dưới dạng thanh tiến trình
Giá trị mặc định¶
Bất kỳ trường nào cũng có thể được cung cấp một giá trị mặc định. Trong định nghĩa trường, hãy thêm tùy chọn default=X
trong đó X
là giá trị bằng chữ Python (boolean, số nguyên, float, chuỗi) hoặc một hàm lấy tập bản ghi và trả về một giá trị:
name = fields.Char(default="Unknown")
user_id = fields.Many2one('res.users', default=lambda self: self.env.user)
Ghi chú
Đối tượng self.env
cấp quyền truy cập vào các tham số yêu cầu và những thứ hữu ích khác:
self.env.cr
hoặcself._cr
là đối tượng con trỏ cơ sở dữ liệu; nó được sử dụng để truy vấn cơ sở dữ liệu
self.env.uid
hoặcself._uid
là id cơ sở dữ liệu của người dùng hiện tại
self.env.user
là bản ghi của người dùng hiện tại
self.env.context
hoặcself._context
là từ điển ngữ cảnh
self.env.ref(xml_id)
trả về bản ghi tương ứng với id XML
self.env[model_name]
trả về một phiên bản của mô hình đã cho
Exercise
Đối tượng hoạt động – Giá trị mặc định
Xác định giá trị mặc định start_date là hôm nay (xem
Date
).Thêm trường
active
trong Phiên của lớp và đặt phiên là hoạt động theo mặc định.
Trao đổi trực tuyến¶
Cơ chế "onchange" cung cấp một cách để giao diện máy khách cập nhật biểu mẫu bất cứ khi nào người dùng điền giá trị vào một trường mà không lưu bất kỳ thứ gì vào cơ sở dữ liệu.
Ví dụ: giả sử một mô hình có ba trường số tiền
, đơn_giá
và giá
và bạn muốn cập nhật giá trên biểu mẫu khi bất kỳ trường nào khác được sửa đổi. Để đạt được điều này, hãy xác định một phương thức trong đó self
đại diện cho bản ghi trong chế độ xem biểu mẫu và trang trí nó bằng onchange()
để chỉ định trường nào nó phải được kích hoạt. Bất kỳ thay đổi nào bạn thực hiện trên self
sẽ được phản ánh trên biểu mẫu.
<!-- content of form view -->
<field name="amount"/>
<field name="unit_price"/>
<field name="price" readonly="1"/>
# onchange handler
@api.onchange('amount', 'unit_price')
def _onchange_price(self):
# set auto-changing field
self.price = self.amount * self.unit_price
# Can optionally return a warning and domains
return {
'warning': {
'title': "Something bad happened",
'message': "It was very bad indeed",
}
}
Đối với các trường được tính toán, hành vi onchange
có giá trị được tích hợp sẵn như có thể thấy bằng cách chơi với biểu mẫu Session: thay đổi số lượng chỗ ngồi hoặc người tham gia và thanh tiến trình taken_seats
được cập nhật tự động.
Exercise
Cảnh báo
Thêm một sự thay đổi rõ ràng để cảnh báo về các giá trị không hợp lệ, chẳng hạn như số lượng ghế âm hoặc nhiều người tham gia hơn số ghế.
Ràng buộc mô hình¶
SoOn cung cấp hai cách để thiết lập các bất biến được xác minh tự động: Ràng buộc Python
và Ràng buộc SQL
.
Ràng buộc Python được định nghĩa là một phương thức được trang trí bằng constrains()
và được gọi trên một tập bản ghi. Trình trang trí chỉ định trường nào có liên quan đến ràng buộc để ràng buộc được đánh giá tự động khi một trong số chúng được sửa đổi. Phương thức này dự kiến sẽ đưa ra một ngoại lệ nếu tính bất biến của nó không được thỏa mãn:
from odoo.exceptions import ValidationError
@api.constrains('age')
def _check_something(self):
for record in self:
if record.age > 20:
raise ValidationError("Your record is too old: %s" % record.age)
# all records passed the test, don't return anything
Exercise
Thêm các ràng buộc Python
Thêm một ràng buộc để kiểm tra xem người hướng dẫn có mặt trong số những người tham dự phiên học của chính họ hay không.
Các ràng buộc SQL được xác định thông qua thuộc tính mô hình _sql_constraints
. Cái sau được gán cho một danh sách gồm ba chuỗi (name, sql_def định, message)
, trong đó name
là tên ràng buộc SQL hợp lệ, sql_def định
là một biểu thức table_constraint và ``message `` là thông báo lỗi.
Exercise
Thêm các ràng buộc SQL
Với sự trợ giúp của Tài liệu của PostgreSQL , hãy thêm các ràng buộc sau:
KIỂM TRA rằng mô tả khóa học và tên khóa học có khác nhau không
Đặt tên khóa học ĐỘC ĐÁO
Exercise
Bài tập 6 - Thêm tùy chọn trùng lặp
Vì chúng tôi đã thêm một ràng buộc về tính duy nhất của Tên khóa học nên không thể sử dụng chức năng "trùng lặp" nữa (
).Triển khai lại phương thức "sao chép" của riêng bạn cho phép sao chép đối tượng Khóa học, thay đổi tên gốc thành "Bản sao của [tên gốc]".
Chế độ xem nâng cao¶
Chế độ xem cây¶
Chế độ xem dạng cây có thể có các thuộc tính bổ sung để tùy chỉnh thêm hành vi của chúng:
trang trí-{$name}
cho phép thay đổi kiểu văn bản của hàng dựa trên thuộc tính của bản ghi tương ứng.
Giá trị là biểu thức Python. Đối với mỗi bản ghi, biểu thức được đánh giá bằng các thuộc tính của bản ghi dưới dạng giá trị ngữ cảnh và nếu
true
, kiểu tương ứng sẽ được áp dụng cho hàng. Dưới đây là một số giá trị khác có sẵn trong ngữ cảnh:uid
: id của người dùng hiện tại,hôm nay
: ngày địa phương hiện tại dưới dạng chuỗi có dạngYYYY-MM-DD
,bây giờ
: giống nhưhôm nay
nhưng có thêm thời gian hiện tại. Giá trị này được định dạng làYYYY-MM-DD hh:mm:ss
.
{$name}
có thể làbf
(font-weight: đậm
),it
(font-style: italic
), hoặc bất kỳ màu ngữ cảnh bootstrap nào (nguy hiểm
,thông tin
, `` tắt tiếng``, `` chính``, `` thành công `` hoặc `` cảnh báo``).<tree string="Idea Categories" decoration-info="state=='draft'" decoration-danger="state=='trashed'"> <field name="name"/> <field name="state"/> </tree>
có thể chỉnh sửa
Hoặc
"trên"
hoặc"dưới"
. Làm cho chế độ xem dạng cây có thể chỉnh sửa tại chỗ (thay vì phải xem qua chế độ xem biểu mẫu), giá trị là vị trí nơi các hàng mới xuất hiện.
Exercise
Danh sách tô màu
Sửa đổi chế độ xem dạng cây Phiên theo cách sao cho các phiên kéo dài dưới 5 ngày có màu xanh lam và các phiên kéo dài hơn 15 ngày có màu đỏ.
Lịch¶
Hiển thị các bản ghi dưới dạng sự kiện lịch. Phần tử gốc của chúng là <calendar>
và các thuộc tính phổ biến nhất của chúng là:
màu sắc
Tên của trường được sử dụng cho phân đoạn màu. Màu sắc được tự động phân phối cho các sự kiện, nhưng các sự kiện trong cùng phân đoạn màu (các bản ghi có cùng giá trị cho trường
@color
của chúng) sẽ có cùng màu.ngày_bắt đầu
trường của bản ghi chứa ngày/giờ bắt đầu cho sự kiện
ngày_stop
(tùy chọn)trường của bản ghi chứa ngày/giờ kết thúc của sự kiện
chuỗi
trường của bản ghi để xác định nhãn cho từng sự kiện lịch
<calendar string="Ideas" date_start="invent_date" color="inventor_id">
<field name="name"/>
</calendar>
Exercise
Xem lịch
Thêm chế độ xem Lịch vào mô hình Phiên cho phép người dùng xem các sự kiện được liên kết với Học viện mở.
Lượt xem tìm kiếm¶
Các phần tử <field>
của chế độ xem tìm kiếm có thể có @filter_domain
ghi đè miền được tạo để tìm kiếm trên trường nhất định. Trong miền nhất định, self
đại diện cho giá trị do người dùng nhập. Trong ví dụ bên dưới, nó được sử dụng để tìm kiếm trên cả hai trường name
và description
.
Chế độ xem tìm kiếm cũng có thể chứa các phần tử <filter>
, đóng vai trò là nút chuyển đổi cho các tìm kiếm được xác định trước. Bộ lọc phải có một trong các thuộc tính sau:
tên miền
thêm tên miền đã cho vào tìm kiếm hiện tại
- `` bối cảnh``
thêm một số ngữ cảnh vào tìm kiếm hiện tại; sử dụng khóa
group_by
để nhóm các kết quả theo tên trường đã cho
<search string="Ideas">
<field name="name"/>
<field name="description" string="Name and description"
filter_domain="['|', ('name', 'ilike', self), ('description', 'ilike', self)]"/>
<field name="inventor_id"/>
<field name="country_id" widget="selection"/>
<filter name="my_ideas" string="My Ideas"
domain="[('inventor_id', '=', uid)]"/>
<group string="Group By">
<filter name="group_by_inventor" string="Inventor"
context="{'group_by': 'inventor_id'}"/>
</group>
</search>
Để sử dụng chế độ xem tìm kiếm không mặc định trong một hành động, nó phải được liên kết bằng trường search_view_id
của bản ghi hành động.
Hành động này cũng có thể đặt giá trị mặc định cho các trường tìm kiếm thông qua trường context
của nó: các khóa ngữ cảnh có dạng search_default_field_name
sẽ khởi tạo field_name với giá trị được cung cấp. Các bộ lọc tìm kiếm phải có @name
tùy chọn để có giá trị mặc định và hoạt động như các boolean (chúng chỉ có thể được bật theo mặc định).
Exercise
Lượt xem tìm kiếm
Thêm nút để lọc các khóa học mà người dùng hiện tại chịu trách nhiệm trong chế độ xem tìm kiếm khóa học. Làm cho nó được chọn theo mặc định.
Thêm nút để nhóm các khóa học theo người dùng có trách nhiệm.
Gantt¶
Cảnh báo
Chế độ xem gantt yêu cầu mô-đun web_gantt có trong phiên bản enterprise.
Biểu đồ thanh ngang thường được sử dụng để hiển thị kế hoạch và tiến độ của dự án, phần tử gốc của chúng là <gantt>
.
<gantt string="Ideas"
date_start="invent_date"
date_stop="date_finished"
progress="progress"
default_group_by="inventor_id" />
Exercise
biểu đồ Gantt
Thêm Biểu đồ Gantt cho phép người dùng xem lịch trình các phiên được liên kết với mô-đun Học viện Mở. Các buổi học nên được nhóm lại theo người hướng dẫn.
Chế độ xem biểu đồ¶
Chế độ xem biểu đồ cho phép tổng hợp và phân tích các mô hình, phần tử gốc của chúng là <graph>
.
Ghi chú
Chế độ xem trục (phần tử <pivot>
) là một bảng nhiều chiều, cho phép lựa chọn trình quay và kích thước để có được tập dữ liệu tổng hợp phù hợp trước khi chuyển sang tổng quan bằng đồ họa hơn. Chế độ xem trục có cùng định nghĩa nội dung với chế độ xem biểu đồ.
Chế độ xem biểu đồ có 4 chế độ hiển thị, chế độ mặc định được chọn bằng thuộc tính @type
.
- Thanh (mặc định)
biểu đồ thanh, thứ nguyên đầu tiên được sử dụng để xác định các nhóm trên trục hoành, các thứ nguyên khác xác định các thanh tổng hợp trong mỗi nhóm.
Theo mặc định, các thanh nằm cạnh nhau, chúng có thể được xếp chồng lên nhau bằng cách sử dụng
@stacked="True"
trên<graph>
- Đường kẻ
Biểu đồ đường 2 chiều
- Bánh
bánh 2 chiều
Chế độ xem biểu đồ chứa <field>
với thuộc tính @type
bắt buộc lấy các giá trị:
hàng
(mặc định)trường này phải được tổng hợp theo mặc định
đo lường
trường nên được tổng hợp thay vì được nhóm trên
<graph string="Total idea score by Inventor">
<field name="inventor_id"/>
<field name="score" type="measure"/>
</graph>
Cảnh báo
Chế độ xem biểu đồ thực hiện tổng hợp các giá trị cơ sở dữ liệu, chúng không hoạt động với các trường được tính toán không được lưu trữ.
Exercise
Chế độ xem biểu đồ
Thêm chế độ xem Biểu đồ trong đối tượng Phiên hiển thị số lượng người tham dự dưới dạng biểu đồ thanh cho mỗi khóa học.
Kanban¶
Được sử dụng để tổ chức các công việc, quy trình sản xuất, v.v… phần tử gốc của chúng là <kanban>
.
Chế độ xem Kanban hiển thị một bộ thẻ có thể được nhóm thành các cột. Mỗi thẻ đại diện cho một bản ghi và mỗi cột là các giá trị của một trường tổng hợp.
Ví dụ: các nhiệm vụ của dự án có thể được sắp xếp theo giai đoạn (mỗi cột là một giai đoạn) hoặc theo trách nhiệm (mỗi cột là một người dùng), v.v.
Chế độ xem Kanban xác định cấu trúc của mỗi thẻ dưới dạng kết hợp các thành phần biểu mẫu (bao gồm HTML cơ bản) và Mẫu QWeb.
Exercise
Chế độ xem Kanban
Thêm chế độ xem Kanban hiển thị các phiên được nhóm theo khóa học (do đó các cột là các khóa học).
Bảo vệ¶
Cơ chế kiểm soát truy cập phải được cấu hình để đạt được chính sách bảo mật mạch lạc.
Cơ chế kiểm soát truy cập dựa trên nhóm¶
Các nhóm được tạo dưới dạng bản ghi thông thường trên mô hình res.groups
và được cấp quyền truy cập menu thông qua định nghĩa menu. Tuy nhiên, ngay cả khi không có menu, các đối tượng vẫn có thể được truy cập gián tiếp, do đó, các quyền thực sự ở cấp độ đối tượng (đọc, ghi, tạo, hủy liên kết) phải được xác định cho các nhóm. Chúng thường được chèn qua tệp CSV bên trong các mô-đun. Cũng có thể hạn chế quyền truy cập vào các trường cụ thể trên chế độ xem hoặc đối tượng bằng thuộc tính nhóm của trường.
Quyền truy cập¶
Quyền truy cập được định nghĩa là các bản ghi của mô hình ir.model.access
. Mỗi quyền truy cập được liên kết với một mô hình, một nhóm (hoặc không có nhóm nào để truy cập toàn cầu) và một tập hợp các quyền: đọc, viết, tạo, hủy liên kết. Các quyền truy cập như vậy thường được tạo bởi tệp CSV được đặt tên theo mô hình của nó: ir.model.access.csv
.
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
access_idea_idea,idea.idea,model_idea_idea,base.group_user,1,1,1,0
access_idea_vote,idea.vote,model_idea_vote,base.group_user,1,1,1,0
Exercise
Thêm kiểm soát truy cập thông qua giao diện SoOn
Tạo người dùng mới "John Smith". Sau đó, tạo một nhóm "OpenAcademy / Session Read" với quyền truy cập đọc vào mô hình Session.
Exercise
Thêm kiểm soát truy cập thông qua các tệp dữ liệu trong mô-đun của bạn
Sử dụng các tập tin dữ liệu,
Tạo một nhóm OpenAcademy / Manager với toàn quyền truy cập vào tất cả các mô hình OpenAcademy
Làm cho Phiên và Khóa học có thể đọc được bởi tất cả người dùng
Ghi lại quy tắc¶
Quy tắc bản ghi hạn chế quyền truy cập vào một tập hợp con các bản ghi của mô hình nhất định. Quy tắc là bản ghi của mô hình ir.rule
và được liên kết với một mô hình, một số nhóm (trường many2many), các quyền áp dụng hạn chế và một miền. Tên miền chỉ định hồ sơ nào có quyền truy cập bị hạn chế.
Dưới đây là ví dụ về quy tắc ngăn chặn việc xóa khách hàng tiềm năng không ở trạng thái hủy
. Lưu ý rằng giá trị của trường groups
phải tuân theo quy ước tương tự như phương thức write()
của ORM.
<record id="delete_cancelled_only" model="ir.rule">
<field name="name">Only cancelled leads may be deleted</field>
<field name="model_id" ref="crm.model_crm_lead"/>
<field name="groups" eval="[(4, ref('sales_team.group_sale_manager'))]"/>
<field name="perm_read" eval="0"/>
<field name="perm_write" eval="0"/>
<field name="perm_create" eval="0"/>
<field name="perm_unlink" eval="1" />
<field name="domain_force">[('state','=','cancel')]</field>
</record>
Exercise
Ghi lại quy tắc
Thêm quy tắc ghi cho Khóa học mẫu và nhóm "OpenAcademy / Manager", hạn chế quyền truy cập write
và unlink
đối với người chịu trách nhiệm về khóa học. Nếu một khóa học không có trách nhiệm thì tất cả người dùng trong nhóm phải có khả năng sửa đổi nó.
pháp sư¶
Trình hướng dẫn mô tả các phiên tương tác với người dùng (hoặc hộp thoại) thông qua các biểu mẫu động. Trình hướng dẫn chỉ đơn giản là một mô hình mở rộng lớp TransientModel
thay vì Model
. Lớp TransientModel
mở rộng Model
và sử dụng lại tất cả các cơ chế hiện có của nó, với các đặc điểm sau:
Các bản ghi thuật sĩ không có nghĩa là phải tồn tại lâu dài; chúng sẽ tự động bị xóa khỏi cơ sở dữ liệu sau một thời gian nhất định. Đây là lý do tại sao chúng được gọi là tạm thời.
Bản ghi thuật sĩ có thể tham chiếu đến các bản ghi thông thường hoặc bản ghi thuật sĩ thông qua các trường quan hệ (many2one hoặc many2many), nhưng các bản ghi thông thường không thể tham chiếu đến các bản ghi thuật sĩ thông qua trường many2one.
Chúng tôi muốn tạo một trình hướng dẫn cho phép người dùng tạo người tham dự cho một phiên cụ thể hoặc cho danh sách các phiên cùng một lúc.
Exercise
Xác định thuật sĩ
Tạo mô hình trình hướng dẫn có mối quan hệ many2one với mô hình Session và mối quan hệ many2many với mô hình Partner.
Khởi chạy trình hướng dẫn¶
Trình hướng dẫn chỉ đơn giản là window actions với trường target
được đặt thành giá trị new
, mở ra dạng xem (thường là a form) trong một hộp thoại riêng. Hành động có thể được kích hoạt thông qua một mục menu, nhưng thường được kích hoạt bằng một nút.
Một cách khác để khởi chạy trình hướng dẫn là thông qua menu bind_model_id
của hành động. Việc đặt trường này sẽ làm cho hành động xuất hiện trên các khung nhìn của mô hình mà hành động đó được "ràng buộc".
<record id="launch_the_wizard" model="ir.actions.act_window">
<field name="name">Launch the Wizard</field>
<field name="res_model">wizard.model.name</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="binding_model_id" ref="model_context_model_ref"/>
</record>
Mẹo
Mặc dù trình hướng dẫn sử dụng các chế độ xem và nút thông thường, nhưng thông thường, việc nhấp vào bất kỳ nút nào trong biểu mẫu trước tiên sẽ lưu biểu mẫu rồi đóng hộp thoại. Bởi vì điều này thường không được mong muốn trong trình hướng dẫn, nên có một thuộc tính đặc biệt special="cancel"
để đóng trình hướng dẫn ngay lập tức mà không lưu biểu mẫu.
Exercise
Khởi chạy trình hướng dẫn
Xác định chế độ xem biểu mẫu cho trình hướng dẫn.
Thêm hành động để khởi chạy nó trong ngữ cảnh của mô hình Phiên.
Xác định giá trị mặc định cho trường phiên trong trình hướng dẫn; sử dụng tham số ngữ cảnh
self._context
để truy xuất phiên hiện tại.
Exercise
Đăng ký người tham dự
Thêm các nút vào trình hướng dẫn và triển khai phương pháp tương ứng để thêm người tham dự vào phiên nhất định.
Exercise
Đăng ký người tham dự nhiều phiên
Sửa đổi mô hình trình hướng dẫn để người tham dự có thể được đăng ký vào nhiều phiên.
Quốc tế hóa¶
Mỗi mô-đun có thể cung cấp bản dịch riêng trong thư mục i18n, bằng cách có các tệp có tên LANG.po trong đó LANG là mã miền địa phương cho ngôn ngữ hoặc kết hợp ngôn ngữ và quốc gia khi chúng khác nhau (ví dụ: pt.po hoặc pt_BR.po). Bản dịch sẽ được SoOn tải tự động cho tất cả các ngôn ngữ được hỗ trợ. Các nhà phát triển luôn sử dụng tiếng Anh khi tạo mô-đun, sau đó xuất các thuật ngữ mô-đun bằng tính năng xuất POT gettext của SoOn (
mà không chỉ định ngôn ngữ), để tạo tệp POT mẫu mô-đun, sau đó lấy ra các tệp PO đã dịch. Nhiều IDE có plugin hoặc chế độ để chỉnh sửa và hợp nhất các tệp PO/POT.Mẹo
Các tệp Đối tượng Di động do SoOn tạo ra được xuất bản trên Transifex, giúp việc dịch phần mềm trở nên dễ dàng.
|- idea/ # The module directory
|- i18n/ # Translation files
| - idea.pot # Translation Template (exported from Odoo)
| - fr.po # French translation
| - pt_BR.po # Brazilian Portuguese translation
| (...)
Mẹo
Theo mặc định, tính năng xuất POT của SoOn chỉ trích xuất các nhãn bên trong các tệp XML hoặc bên trong các định nghĩa trường trong mã Python, nhưng bất kỳ chuỗi Python nào cũng có thể được dịch theo cách này bằng cách bao quanh nó bằng hàm odoo._()
(ví dụ: _("Label ")
)
Exercise
Dịch một mô-đun
Chọn ngôn ngữ thứ hai để cài đặt SoOn của bạn. Dịch mô-đun của bạn bằng cách sử dụng các tiện ích do SoOn cung cấp.
Báo cáo¶
Báo cáo in¶
SoOn sử dụng công cụ báo cáo dựa trên Mẫu QWeb, Twitter Bootstrap và Wkhtmltopdf.
Một báo cáo là sự kết hợp của hai yếu tố:
một
ir.actions.report
cấu hình các tham số cơ bản khác nhau cho báo cáo (loại mặc định, liệu báo cáo có được lưu vào cơ sở dữ liệu sau khi tạo hay không,…)<record id="account_invoices" model="ir.actions.report"> <field name="name">Invoices</field> <field name="model">account.invoice</field> <field name="report_type">qweb-pdf</field> <field name="report_name">account.report_invoice</field> <field name="report_file">account.report_invoice</field> <field name="attachment_use" eval="True"/> <field name="attachment">(object.state in ('open','paid')) and ('INV'+(object.number or '').replace('/','')+'.pdf')</field> <field name="binding_model_id" ref="model_account_invoice"/> <field name="binding_type">report</field> </record>
Mẹo
Bởi vì nó lớn hơn là một hành động tiêu chuẩn, như với pháp sư, nói chung là hữu ích khi thêm báo cáo dưới dạng mục ngữ cảnh trên cây và / hoặc dạng xem biểu mẫu của mô hình được báo cáo thông qua ` trường
bind_model_id`
.Ở đây, chúng tôi cũng đang sử dụng
bind_type
để báo cáo nằm trong menu ngữ cảnh report thay vì menu hành động. Không có sự khác biệt về mặt kỹ thuật nhưng việc đặt các yếu tố vào đúng vị trí sẽ giúp ích cho người dùng.Một Chế độ xem QWeb tiêu chuẩn cho báo cáo thực tế:
<t t-call="web.html_container"> <t t-foreach="docs" t-as="o"> <t t-call="web.external_layout"> <div class="page"> <h2>Report title</h2> </div> </t> </t> </t>
bối cảnh hiển thị tiêu chuẩn cung cấp một số thành phần, trong đó quan trọng nhất là:
tài liệu
các bản ghi mà báo cáo được in
người dùng
người dùng in báo cáo
Vì báo cáo là các trang web tiêu chuẩn nên chúng có sẵn thông qua URL và các thông số đầu ra có thể được điều chỉnh thông qua URL này, ví dụ: phiên bản HTML của báo cáo Invoice có sẵn thông qua http://localhost:8069/report/html/account .report_invoice/1 (nếu tài khoản
được cài đặt) và phiên bản PDF thông qua http://localhost:8069/report/pdf/account.report_invoice/1.
Nguy hiểm
Nếu có vẻ như báo cáo PDF của bạn thiếu kiểu (tức là văn bản xuất hiện nhưng kiểu/bố cục khác với phiên bản html), có thể quá trình wkhtmltopdf của bạn không thể truy cập máy chủ web để tải chúng xuống.
Nếu bạn kiểm tra nhật ký máy chủ của mình và thấy rằng các kiểu CSS không được tải xuống khi tạo báo cáo PDF thì chắc chắn đây là sự cố.
Quá trình wkhtmltopdf sẽ sử dụng tham số hệ thống web.base.url
làm đường dẫn gốc tới tất cả các tệp được liên kết, nhưng tham số này được cập nhật tự động mỗi khi Quản trị viên đăng nhập. Nếu máy chủ của bạn nằm phía sau một số loại proxy, không thể truy cập được. Bạn có thể khắc phục điều này bằng cách thêm một trong các tham số hệ thống sau:
report.url
, trỏ đến một URL có thể truy cập được từ máy chủ của bạn (có thể làhttp://localhost:8069
hoặc một cái gì đó tương tự). Nó sẽ chỉ được sử dụng cho mục đích cụ thể này.web.base.url.freeze
, khi được đặt thànhTrue
, sẽ dừng cập nhật tự động thànhweb.base.url
.
Exercise
Tạo báo cáo cho mô hình Phiên
Đối với mỗi phiên, nó sẽ hiển thị tên phiên, thời điểm bắt đầu và kết thúc cũng như liệt kê những người tham dự phiên.
Trang tổng quan¶
Exercise
Xác định Bảng điều khiển
Xác định trang tổng quan chứa chế độ xem biểu đồ bạn đã tạo, chế độ xem lịch phiên và chế độ xem danh sách các khóa học (có thể chuyển sang chế độ xem biểu mẫu). Trang tổng quan này sẽ có sẵn thông qua một mục menu trong menu và tự động hiển thị trong ứng dụng khách web khi menu chính OpenAcademy được chọn.