「Odoo 基礎教程系列」第三篇——從 Todo 應用開始(2)

Powered by @rawpixel

在這篇教程裏咱們將會了解到 Odoo 模型裏的一些其餘類型的字段和特殊機制,而我依然會繼續帶領你們一塊兒完善咱們的 Todo 應用,不斷地往裏面添加一些新的功能特性,讓它看起來更豐滿也更實用一些。python

選擇字段

在上一篇教程中,咱們已經建立好了待辦事項的模型,可是隻是添加了「描述」和「已完成?」兩個字段,這確定是不能知足咱們的需求的。如今咱們來給待辦事項增長一個「緊急程度」的字段,用來表示當前任務的優先級。git

# models.py
class TodoTask(models.Model):
    _name = 'todo.task'
    _description = '待辦事項'

    name = fields.Char('描述', required=True)
    is_done = fields.Boolean('已完成?')
    priority = fields.Selection([
        ('todo', '待辦'),
        ('normal', '普通'),
        ('urgency', '緊急')
    ], default='todo', string='緊急程度')

咱們添加了一個 Selection 類型的字段 priority,而且指定了三個可供選擇的程度類型,通常狀況下,若是一個字段只有固定的幾種可選值,一般都會選擇使用 Selection 字段,它接受一個元組列表做爲參數,其中元組的組成爲 (value, string),左邊的是數據庫中存儲的值,右邊的是一個用於界面顯示的描述。github

此處咱們還給這個字段添加了默認值 todo,表示當一個待辦事項被建立後,若是沒有指定緊急程度,將默認是待辦狀態。咱們能夠爲任意類型的字段添加默認值shell

在上一篇教程中咱們提到過,在對模型進行改動以後,須要對模塊進行升級才能看到變動後的樣子,除了從應用列表中找到模塊進行升級外,咱們還能夠在命令行中給 Odoo 的啓動命令加上參數 -u todo 指定升級 todo 模塊。數據庫

./odoo-bin --addons-path=addons,../mymodules --db-filter=^demo$ -d demo -u todo

緊急程度

升級後建立或打開任意一條待辦事項進入到表單頁面,就能夠看到已經多了「緊急程度」這個字段了,而且默認選擇了「待辦」這一狀態。小程序

日期字段

咱們已經給待辦事項加上緊急程度了,但是光有這個還不夠,咱們還要給它加上截止時間,畢竟 deadline 是第一輩子產力呀!api

# models.py
deadline = fields.Datetime(u'截止時間')

咱們把截止日期也放到 TreeView 中,方便查看各個任務的 deadline微信

<!-- views.xml -->
<field name="arch" type="xml">
    <tree string="Todo">
        <field name="name"/>
        <field name="deadline"/>
        <field name="is_done"/>
    </tree>
</field>

截止時間 FormView

計算字段與視圖裝飾器

不少時候咱們會須要用不一樣的顏色對待辦事項進行標記,例如咱們會但願已通過期的任務以紅色標記來提醒咱們,這個任務過時了。任務是否已通過期,咱們要先知道任務的截止時間(上面一小節已經加上了)和當前時間,而後進行比較判斷任務的截止時間是否小於當前時間,若是是則表示任務已通過期了,咱們須要在視圖上用紅色將對應的任務標記起來。那將這個需求轉化成代碼應該怎麼作呢?ui

這個需求跟時間有關,而且時間是流動(一直在變化)的,因此咱們應該要有一個方法在用戶每次打開待辦事項以前,把這個結果計算好,而且反饋給用戶,還好 Odoo 的 ORM 已經爲咱們實現了相關的機制——計算字段(Computed fieldsspa

# models.py
is_expired = fields.Boolean(u'已過時', compute='_compute_is_expired')

@api.depends('deadline')
@api.multi
def _compute_is_expired(self):
    for record in self:
        if record.deadline:
            record.is_expired = record.deadline < fields.Datetime.now()
        else:
            record.is_expired = False

計算字段其實和其餘字段同樣,只不過多了一個 compute 屬性,它的值是計算這個字段值的方法名。咱們來看一下對應的方法 _compute_is_expired 頭頂上的 @api.depends 這個裝飾器,它接受了一個參數 deadline,表示的是 is_expired 這個字段的計算會用到 deadline 這個字段的值(咱們須要用它的值和當前時間進行比較),若是一個計算字段會用到多個其餘字段的值,這裏就須要以逗號分隔,將用到的值的字段名依次傳入裝飾器中。

@api.multi 則表示該方法中的 self 是一個記錄集(多個實例的集合),若是不理解,能夠暫時不深究,到後面天然會知道這裏的實際用法。

再來看看實際的計算邏輯部分,只有一個循環以及一條賦值語句,剛剛已經提到過這裏的 self 表示一個記錄集,咱們須要對這個記錄集裏的每一條記錄進行計算,判斷這個待辦事項是否已通過期,這裏的 record 就是每一條記錄的實例對象,咱們用這條記錄的 deadline 的值和當前時間 fields.Datetime.now() 進行比較,而後將結果賦值給字段 is_expired,就是這麼簡單。

PS: 這裏咱們對 deadline 進行了判斷,是由於若是沒有設置截止時間,又或者是在新建代辦事項時,這裏的 deadline 會是一個布爾值,是不能和時間字符串進行比較的。

其中你們可能會有疑問的應該是當前時間的獲取,爲何不是用 datetime.now() 吧?實際上獲取當前時間用的也是這個方法,只不過 Odoo 的 ORM 替咱們封裝了一層,fields.Datetime.now() 是類 Datetime 的靜態方法:

# fields.py
class Datetime(Field):
    type = 'datetime'
    column_type = ('timestamp', 'timestamp')
    column_cast_from = ('date',)

    @staticmethod
    def now(*args):
        """ Return the current day and time in the format expected by the ORM.
            This function may be used to compute default values.
        """
        return datetime.now().strftime(DATETIME_FORMAT)

好的,這裏先不過多糾結細節問題,如今咱們已經能夠計算出來每一個待辦事項是否已通過期了,那要怎麼去用這個計算字段呢?咱們打開視圖文件來加點東西上去:

<!-- views.xml -->
<field name="arch" type="xml">
    <tree string="Todo" decoration-danger="is_expired">
        <field name="name"/>
        <field name="deadline"/>
        <field name="is_done"/>
        <field name="is_expired" invisible="True"/>
    </tree>
</field>

在視圖中咱們把 is_expired 字段加了進去,而且還加上了屬性 invisible,這個屬性的做用是將當前字段隱藏起來,由於這裏咱們不但願用戶看到這個字段的值,而是將結果反映在顏色上。而後咱們再看到 <tree /> 標籤多了一個屬性 decoration-danger,這個屬性能夠接受表達式或字段名做爲值,當結果爲真時,這個屬性就會生效,將 TreeView 中知足表達式的行以紅色標記,實際的效果以下:

過時任務

今天這篇教程的內容就先到這裏了,下一篇再繼續帶你們深刻更多的內容。這篇教程中的代碼一樣會更新在個人 GitHub 倉庫中。

倉庫地址:Odoo-Tutorial-Demo

寫在最後

距離上一次更新,已通過了好幾個月了,這段時間除了忙公司的事情,還額外在作一些別的東西,而後最近在開發一個小程序。一直很想抽空出來更新這個系列的教程,一邊又有不少事情在忙,拖更了實在是抱歉了!

若是你有任何的疑問,歡迎留言,我將會盡快給出答覆,若是想要加羣或者加好友,能夠發送站內信給我,我會回覆你微信號~

期待下一篇教程能夠繼續和大家見面。

相關文章
相關標籤/搜索