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:

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>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.

Hành động và Menu

Các hành động và menu là các bản ghi thông thường trong cơ sở dữ liệu, thường được khai báo thông qua các tệp dữ liệu. Các hành động có thể được kích hoạt theo ba cách:

  1. bằng cách nhấp vào các mục menu (được liên kết với các hành động cụ thể)

  2. bằng cách nhấp vào các nút trong chế độ xem (nếu chúng được kết nối với hành động)

  3. như các hành động theo ngữ cảnh trên đối tượng

Bởi vì việc khai báo các menu hơi phức tạp nên có một phím tắt <menuitem> để khai báo một ir.ui.menu và kết nối nó với hành động tương ứng dễ dàng hơn.

<record model="ir.actions.act_window" id="action_list_ideas">
    <field name="name">Ideas</field>
    <field name="res_model">idea.idea</field>
    <field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_ideas" parent="menu_root" name="Ideas" sequence="10"
          action="action_list_ideas"/>

Nguy hiểm

Hành động phải được khai báo trước menu tương ứng của nó trong tệp XML.

Các tệp dữ liệu được thực thi tuần tự, id của hành động phải có trong cơ sở dữ liệu trước khi có thể tạo menu.

Exercise

Xác định các mục menu mới

Xác định các mục menu mới để truy cập các khóa học trong mục menu OpenAcademy. Người dùng sẽ có thể:

  • hiển thị danh sách tất cả các khóa học

  • tạo/sửa đổi các khóa học

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

khóa ngoại

One2many(other_model, liên quan_field)

Một mối quan hệ ảo, nghịch đảo của Many2one. A One2many 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ường Many2one trong other_model và tên của nó phảirel_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 CourseSession để 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.

../../_images/inheritance_methods.png

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ợp

thay 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ốc

trước

chèn phần thân của xpath làm anh em trước phần tử phù hợp

sau

chèn phần thân của xpaths làm phần tử anh em sau phần tử đã so khớp

thuộ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ân xpath

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ác

  • Sử 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 1Giá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)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ặc self._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ặc self._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ặc self._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á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 PythonRà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``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:

  1. KIỂM TRA rằng mô tả khóa học và tên khóa học có khác nhau không

  2. Đặ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 (Form ‣ Duplicate).

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ạng YYYY-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>
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 namedescription.

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

  1. 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.

  2. 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ênKhó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 writeunlink đố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 Action của chế độ xem dạng cây hoặc biểu mẫu. Việc này được thực hiện thông qua trường 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

  1. Xác định chế độ xem biểu mẫu cho trình hướng dẫn.

  2. Thêm hành động để khởi chạy nó trong ngữ cảnh của mô hình Phiên.

  3. 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 (Settings ‣ Translations ‣ Import/Export ‣ Xuất dịch 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 BootstrapWkhtmltopdf.

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ành True, sẽ dừng cập nhật tự động thành web.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.

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 cẩn thận vì nó bỏ qua tất cả các cơ chế bảo mật và xác thực của SoOn.