建立一個Odoo Module (二)- Basic views、Relational fields

Basic Views

Views 定義了 model 中的 record 的展現方式,每種類型的 view 都代提供了 model 的一種數據可視化(list 展現, 圖表的方式展現,等), views 可以通過他們的 type (e.g. a list of partners)或者明確指定它的 external id 來被請求。對於一般的請求來說,the view with 正確的 type 和 最低優先級的 將被調用(所以, the lowest-priority view of each type 就是 默認view of each type)
view 的繼承機制,使得我們可以在任意地方對該view進行添加或者刪除其中的元素。

Generic view declaration

A View 就被聲明爲一個record,不過這個record的 model 是 ir.ui.view。 view type 將在 record 的 arch field 中設置

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

Tree views

Tree views 通常也被稱爲 list views,以表格的方式展現所有 records
root element 是 <tree>,最普遍的就是將model的所有字段展現出來,每個 field 就是一個 column

<tree string="Idea list">
    <field name="name"/>
    <field name="inventor_id"/>
</tree>

Form Views

Forms 是用來新建和修改 單一 record
root element 是 <form> ,它集成了 高度結構化的 elements (groups, notebook) 還有交互式的 element(buttons and fields):

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



練習 2-1

通過XML 爲Course object 設置 from view

openacademy/views/openacademy.xml

<?xml version="1.0" encoding="UTF-8"?>
<openerp>
    <data>
        <!-- 新增 -->
        <record model="ir.ui.view" id="course_form_view">
            <field name="name">course.form</field>
            <field name="model">openacademy.course</field>
            <field name="arch" type="xml">
                <form string="Course Form">
                    <sheet>
                        <group>
                            <field name="name"/>
                        </group>
                        <notebook>
                            <page string="Description">
                                <field name="description"/>
                            </page>
                            <page string="About">
                                This is an example of notebooks
                            </page>
                        </notebook>
                    </sheet>
                </form>
            </field>
        </record>
        <!-- 結束 -->
        <!-- window action -->
        <!--
            The following tag is an action definition for a "window action",



Form views 也可以使用普通的HTML

<form string="Idea Form">
    <header>
        <button string="Confirm" type="object" name="action_confirm"
                states="draft" class="oe_highlight" />
        <button string="Mark as done" type="object" name="action_done"
                states="confirmed" class="oe_highlight"/>
        <button string="Reset to draft" type="object" name="action_draft"
                states="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>

Search views

Search views 定製了 search field 用以在 list view 或者 其它aggregated views 中進行篩選。root element 就是 <search> ,在這其中就包含了,哪些 field 是可以被 search 的

<search>
    <field name="name"/>
    <field name="inventor_id"/>
</search>

如果沒有設置 search view,那麼Odoo將自動生成一個 search view,但是隻包含model中 name 字段。這也是爲什麼上一章講到 name 是 特殊字段。



練習 2-2
爲course 添加 search view,可以通過 title 或者 description 搜索到

openacademy/views/openacademy.xml

            </field>
        </record>
        <!-- 新增 -->
        <record model="ir.ui.view" id="course_search_view">
            <field name="name">course.search</field>
            <field name="model">openacademy.course</field>
            <field name="arch" type="xml">
                <search>
                    <field name="name"/>
                    <field name="description"/>
                </search>
            </field>
        </record>
        <!-- 結束 -->

        <!-- window action -->
        <!--
            The following tag is an action definition for a "window action",

Relations between models

一個 model 的 record 可能會關聯到另一個 model 的 record。比如,一個銷售訂單 record 會包含客戶 record,在客戶record中含有客戶的相關數據;而且,銷售訂單record 裏面通常還有 sale order line records.



練習 2-3
創建一個 會議 model , session model
在 module Open Acadmy中,我們希望的 session model 是 在 course 的基礎上,在某時間段,有一定的參與人數的會議。
對 session 創建一個model, 包括 name, start date, duration and a number of seats。再添加 action 和 menu 用以展現 sessions,

  1. 創建 class Session in openacademy/models.py
  2. 添加 access to the session object in openacademy/view/openacademy.xml

openacademy/models.py


    name = fields.Char(string="Title", required=True)
    description = fields.Text()


class Session(models.Model):
    _name = 'openacademy.session'

    name = fields.Char(required=True)
    start_date = fields.Date()
    # 6代表浮點數的total number, 2代表有兩位小數
    duration = fields.Float(digits=(6, 2), help="Duration in days")
    seats = fields.Integer(string="Number of seats")

openacademy/views/openacademy.xml

        <!-- Full id location:
             action="openacademy.course_list_action"
             It is not required when it is the same module -->

        <!-- 新增 -->
        <!-- session form view -->
        <record model="ir.ui.view" id="session_form_view">
            <field name="name">session.form</field>
            <field name="model">openacademy.session</field>
            <field name="arch" type="xml">
                <form string="Session Form">
                    <sheet>
                        <group>
                            <field name="name"/>
                            <field name="start_date"/>
                            <field name="duration"/>
                            <field name="seats"/>
                        </group>
                    </sheet>
                </form>
            </field>
        </record>

        <record model="ir.actions.act_window" id="session_list_action">
            <field name="name">Sessions</field>
            <field name="res_model">openacademy.session</field>
            <field name="view_type">form</field>
            <field name="view_mode">tree,form</field>
        </record>

        <menuitem id="session_menu" name="Sessions"
                  parent="openacademy_menu"
                  action="session_list_action"/>
        <!-- 結束 -->
    </data>
</openerp>

Relational fields

Relational fields 將同一 model 的records 連接起來(通常表示層級的關係),或者不同model的 records連接起來。
field types 有:

  • Many2one(other_model, ondelete=’set null’)

使用方式爲

print foo.other_id.name
  • One2many(other_model, related_field)

一種虛擬的關係,和Many2one相反,一個 One2many 通常包含多個records,所以需要使用loop語句

for other in foo.other_ids:
    print other.name

由於 One2many 是虛擬關係,所以必須有一個 other_model,而且 other_model 中必須有一個 Many2one field,且 field name 必須爲 related_field

  • Many2many(other_model)

雙向多對多的關係,任意方的 record 都可以link 到 對面的 多個 records

for other in foo.other_ids:
    print other.name



練習 2-4
使用 many2one,使 model Course and Session 相互關聯起來

  • A course 應該有一個負責人 responsible user, 這個field 應該關聯到一個 Odoo 的內建 model : res.users
  • A session 有一個教員 instructor, 關聯到內建model : res.partner
  • A session 關聯到 a course ,就是 model: openacademy.course, 並且設置 required=True
  • 修改 Views

openacademy/models.py

    name = fields.Char(string="Title", required=True)
    description = fields.Text()

    # 新增
    responsible_id = fields.Many2one('res.users',
        ondelete='set null', string="Responsible", index=True)
    # 結束

class Session(models.Model):
    _name = 'openacademy.session'
    start_date = fields.Date()
    duration = fields.Float(digits=(6, 2), help="Duration in days")
    seats = fields.Integer(string="Number of seats")

    # 新增
    instructor_id = fields.Many2one('res.partner', string="Instructor")
    course_id = fields.Many2one('openacademy.course',
        ondelete='cascade', string="Course", required=True)
    # 結束

openacademy/views/openacademy.xml

                    <sheet>
                        <group>
                            <field name="name"/>
                            <!-- 新增 -->
                            <field name="responsible_id"/>
                            <!-- 結束 -->
                        </group>
                        <notebook>
                            <page string="Description">
            </field>
        </record>
        <!-- 新增 -->
        <!-- override the automatically generated list view for courses -->
        <record model="ir.ui.view" id="course_tree_view">
            <field name="name">course.tree</field>
            <field name="model">openacademy.course</field>
            <field name="arch" type="xml">
                <tree string="Course Tree">
                    <field name="name"/>
                    <field name="responsible_id"/>
                </tree>
            </field>
        </record>
        <!-- 結束 -->

        <!-- window action -->
        <!--
            The following tag is an action definition for a "window action",
                <form string="Session Form">
                    <sheet>
                        <group>
                            <!-- 新增 -->
                            <group string="General">
                                <field name="course_id"/>
                                <field name="name"/>
                                <field name="instructor_id"/>
                            </group>
                            <group string="Schedule">
                                <field name="start_date"/>
                                <field name="duration"/>
                                <field name="seats"/>
                            </group>
                            <!-- 結束 -->
                        </group>
                    </sheet>
                </form>
            </field>
        </record>
        <!-- 新增 -->
        <!-- session tree/list view -->
        <record model="ir.ui.view" id="session_tree_view">
            <field name="name">session.tree</field>
            <field name="model">openacademy.session</field>
            <field name="arch" type="xml">
                <tree string="Session Tree">
                    <field name="name"/>
                    <field name="course_id"/>
                </tree>
            </field>
        </record>
        <!-- 結束 -->

        <record model="ir.actions.act_window" id="session_list_action">
            <field name="name">Sessions</field>
            <field name="res_model">openacademy.session</field>

練習 2-5
通過使用 one2many field, 修改模型以反映course和session之間的關係。

openacademy/models.py

    responsible_id = fields.Many2one('res.users',
        # 新增
        ondelete='set null', string="Responsible", index=True)
    session_ids = fields.One2many(
        'openacademy.session', 'course_id', string="Sessions")
        # 結束


class Session(models.Model):

openacademy/views/openacademy.xml

                            <page string="Description">
                                <field name="description"/>
                            </page>
                            <!-- 新增 -->
                            <page string="Sessions">
                                <field name="session_ids">
                                    <tree string="Registered sessions">
                                        <field name="name"/>
                                        <field name="instructor_id"/>
                                    </tree>
                                </field>
                            </page>
                            <!-- 結束 -->
                        </notebook>
                    </sheet>

練習 2-6
通過使用many2many field, 修改 session model 使其 每個session 都與一定數目的 attendees,attendees 來自 內建model res.parter

openacademy/models.py

    instructor_id = fields.Many2one('res.partner', string="Instructor")
    course_id = fields.Many2one('openacademy.course',
        ondelete='cascade', string="Course", required=True)
    # 新增    
    attendee_ids = fields.Many2many('res.partner', string="Attendees")
    # 結束

openacademy/views/openacademy.xml

                                <field name="seats"/>
                            </group>
                        </group>
                        <!-- 新增 -->
                        <label for="attendee_ids"/>
                        <field name="attendee_ids"/>
                        <!-- 結束 -->
                    </sheet>
                </form>
            </field>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章