iT邦幫忙

2023 iThome 鐵人賽

DAY 13
0
Odoo

Odoo 魔法學院: 一步一腳印帶你成為客製化大師系列 第 13

[Day13]結合odoo已有功能來擴充應用程式

  • 分享至 

  • xImage
  •  

今日目標

今天會來學習其他繼承的機制,用來擴充我們的應用程式,總共會有4種,分別是:

  • Classical inheritanceOdoo (使用現有model作為基礎建立model,新model從其基礎中獲取fields, methods and meta-information)
  • Delegation inheritance (在現有model裡,嵌入另一種model)
  • Prototype inheritance(擁有獨立的資料庫跟資料且新增的功能不會添加到現有model)[但較少使用]
  • Mixin classes (可以儲存功能,再結合到其他model)[不太會單獨使用]

Classic extension

我們先用classic extension擴充model,根據原有model定義要更改或新增的欄位屬性,我們會做:

  • isbn 支援10位數
  • publisher_id 上新增索引,提高搜索效率

先到library_member/models/library_book.py新增以下:

    isbn = fields.Char(help="Use a valid ISBN-13 or ISBN-10.")
    publisher_id = fields.Many2one(index=True)

再到添加,這樣就能讓check ISBN支援10位碼:

    def _check_isbn(self):
        self.ensure_one()
        digits = [int(x) for x in self.isbn if x.isdigit()]
        if len(digits) == 10:
            ponderators = [1, 2, 3, 4, 5, 6, 7, 8, 9]
            total = sum(a * b for a, b in zip(digits[:9], ponderators))
            check = total % 11
            return digits[-1] == check
        else:
            return super()._check_isbn()

Delegation inheritance

這種繼承方式,比較不像物件繼承,比較像物件組合。
等等要實作的是要讓會員可以借書,並擁有借書卡,會員資料會組合在一起,而不是繼承。
先在library_member/model/init.py:

from . import library_member

到library_member/models/library_member.py

from odoo import fields, models


class Member(models.Model):
    _name = "library.member"
    _description = "Library Member"
    _inherits = {"res.partner": "partner_id"}
    _inherit = ["mail.thread", "mail.activity.mixin"]

    card_number = fields.Char()
    partner_id = fields.Many2one(
        "res.partner", delegate=True, ondelete="cascade", required=True
    )

要完成這個model還要新增安全性ACL、menu item和 view:
新增安全性ACL,library_member/security/ir.model.access.csv

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_member_user,Member User  # 跟下面的要連著

Access,model_library_member,library_app.library_group_user,1,1,1,0
access_member_manager,Member # 要跟下面的連著

ManagerAccess,model_library_member,library_app.library_group_manager,1,1,1,1

新增 menu item,library_member/views/library_menu.xml

<odoo>
    <menuitem id="menu_library_member"
      name="Members"
      action="action_library_member"
      parent="library_app.menu_library" />
</odoo>

新增view,library_member/views/member_view.xml

<odoo>

  <record id="view_form_member" model="ir.ui.view">
    <field name="name">Library Member Form
      View</field>
    <field name="model">library.member</field>
    <field name="arch" type="xml">
    
      <form>
        <group>
          <field name="name" />
          <field name="email" />
          <field name="card_number" />
        </group>
      </form>
    </field>
  </record>

  <record id="view_tree_member" model="ir.ui.view">
    <field name="name">Library Member List
      View</field>
    <field name="model">library.member</field>
    <field name="arch" type="xml">
      <tree>
          <field name="name" />
          <field name="card_number" />
      </tree>
    </field>
  </record>
</odoo>

最後要到library_member/manifest.py宣告

"data": [
        "security/ir.model.access.csv",
        "views/book_view.xml",
        "views/library_menu.xml",
    ],

升級model後,就能使用這個擴充model。

Mixin classes

這邊要練習將message chatter and activity mixins 兩種功能結合到library_member上,
要到library_member/manifest.py修改depend mail

"depends": ["library_app", "mail"],

到library_member/models/library_member.py 新增

_inherit = ["mail.thread", "mail.activity.mixin"]

最後再到library_member/views/member_view.xml,新增mail mixin field那邊的code

<record id="view_form_member" model="ir.ui.view">
    <field name="name">Library Member Form
      View</field>
    <field name="model">library.member</field>
    <field name="arch" type="xml">
      <form>
        <group>
          <field name="name" />
          <field name="email" />
          <field name="card_number" />
        </group>
        <!-- add mail mixin field -->
        <div class="oe_chatter">
            <field name="message_follower_ids"
                   widget="mail_followers"/>
            <field name="activity_ids"
                   widget="mail_activity"/>
            <field name="message_ids"
                   widget="mail_thread"/>
        </div>
      </form>
    </field>
  </record>

這樣到library Members form 就能使用留言版的功能,也有給web client使用的一些功能。


上一篇
[Day12] 圖書館管理系統 擴充功能
下一篇
[Day14]修改使用者介面+web頁面
系列文
Odoo 魔法學院: 一步一腳印帶你成為客製化大師30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
大河
iT邦新手 3 級 ‧ 2023-09-28 23:19:49

語法小推薦 enumerate
method _check_isbn 下方兩行的可以簡化

ponderators = [1, 2, 3, 4, 5, 6, 7, 8, 9]
total = sum(a * b for a, b in zip(digits[:9], ponderators))

改用 enumerate,可以省掉宣告 ponderators

total = sum(a * b for a, b in enumerate(digits[:9], start=1))

而我個人的寫法會變成這樣,任何不符合規則的都先提早離開 method,儘量讓主程式在同一階層,分享給您

def _check_isbn(self) -> bool:
    self.ensure_one()
    digits = [int(x) for x in self.isbn if x.isdigit()]
    
    if not len(digits) == 10:
        return super()._check_isbn()
        
    check = sum(i * d for i, d in enumerate(digits[:9], start=1)) % 11
    return digits[-1] == check

PS:最後兩行也可以省略成一行,但後續可能回憶會太亂還是保留兩行

嗨嗨,感謝指點,
很認同你的重構,大大提升了可讀性,還補上 type hint,Python 的功力真高!

我們寫的比較倉促,想要一路從 Model 做到 Front-end,程式還沒整理完,之後每章節會補上 git commit。

我要留言

立即登入留言