入坑odoo 三(創(chuàng)建自定義模塊(1))

前提:odoo python3安裝完成,如若未能完成安裝,請(qǐng)查看我之前的文章,可能對(duì)你有所幫助。
入坑odoo 一 (postgresql安裝)
入坑odoo 二(odoo12安裝)
本人也只是一邊學(xué)習(xí),一邊記錄學(xué)習(xí)的過(guò)程,如果對(duì)各位小伙伴有用,那便是極好的。同樣,可能文章中有錯(cuò)的地方,如果各位小伙伴發(fā)現(xiàn)了,請(qǐng)給我留言,謝謝!
OK,那么開始正題。

創(chuàng)建模塊
1.我們?cè)趏doo源碼所在的目錄創(chuàng)建一個(gè)文件夾mkdir mymodules,mymodules是文件的名字,也可以根據(jù)自己的想法取。這個(gè)文件專門用于存放我們自己創(chuàng)建的模塊,也和odoo自帶的模塊分開來(lái)。
2.使用odoo-bin的腳手架創(chuàng)建一個(gè)空的odoo模塊,里面包含來(lái)一個(gè)完整項(xiàng)目所需的基本文件和項(xiàng)目結(jié)構(gòu)。

#在終端進(jìn)入odoo項(xiàng)目文件,輸入以下命令
./odoo-bin scaffold todo mymodules    
#todo是我們創(chuàng)建的模塊名字,mymodules,是我們存放模塊的文件目錄

結(jié)構(gòu)說(shuō)明
todo
├── init.py
├── manifest.py
├── controllers
│ ├── init.py
│ └── controllers.py
├── demo
│ └── demo.xml
├── models
│ ├── init.py
│ └── models.py
├── security
│ └── ir.model.access.csv
└── views
├── templates.xml
└── views.xml
具體結(jié)構(gòu)就是這樣,但你們讓我說(shuō),我說(shuō)不明白,如果小伙伴想知道的話,本人推薦一個(gè)odoo 教程系列,我也是從那學(xué)的,地址
OK,結(jié)構(gòu)說(shuō)明我們就算過(guò)了哦。

創(chuàng)建模型
首先打開 models/models.py 將里面注釋掉的內(nèi)容刪掉,不要修改文件頂部引入的包,然后添加以下代碼:

class TodoTask(models.Model):
     _name = 'todo.task'
     _description = '待辦事項(xiàng)'

     name = fields.Char('描述', required=True)
     is_done = fields.Boolean('已完成?')

看起來(lái)十分簡(jiǎn)單,第一個(gè)模型就這樣創(chuàng)建好了 :)

我們創(chuàng)建了一個(gè)叫做 TodoTask 的類,它繼承自基礎(chǔ)模型 models.Model,這也是我們使用 Odoo 開發(fā)時(shí)最常用的一種用于持久化數(shù)據(jù)的基礎(chǔ)模型,除此之外還有 models.TransientModelmodels.AbstractModel 這兩種,在之后接觸到我們將會(huì)進(jìn)行講解,這里暫不涉獵。

先看一下這個(gè)模型里帶下劃線前綴的兩個(gè)屬性:

_name - 模型的名稱,在外鍵或者實(shí)例化模型對(duì)象時(shí)會(huì)用到,是模型的唯一標(biāo)識(shí)
_description - 模型的描述,描述模型的作用,一般情況下不會(huì)主動(dòng)使用到
除了上面列出的兩個(gè)特殊屬性外,還有一些其他屬性,例如更改默認(rèn)顯示名稱時(shí)會(huì)用到 _rec_name,繼承現(xiàn)有模型時(shí)會(huì)用到 _inherit 等,這些特殊屬性都具有他們各自的用途,但是除了 _name 是定義一個(gè)新的模型時(shí)必須要有的屬性外,其他屬性都是可選的。

在 Odoo 的模型定義中,我們使用 fields 進(jìn)行字段的定義,在上面這個(gè)模型里,我們簡(jiǎn)單地定義了 nameis_done 兩個(gè)字段,它們的類型分別是 CharBoolean,并且我們指定字段 name 是必填的(添加了required=True)。如果小伙伴接觸過(guò) Django,可能就會(huì)說(shuō)了,DjangoCharField 是必須指定最大長(zhǎng)度 max_length 的,Odoo 的不需要嗎?那最大長(zhǎng)度是多少呢?對(duì)于這個(gè)疑問(wèn),官方的文檔里有這樣一句說(shuō)明:

Basic string field, can be length-limited, usually displayed as a single-line string in clients.

也就是說(shuō) Odoo 的字段類型 Char 是不限制長(zhǎng)度的,但是通常只是用于單行字符串,如果要存儲(chǔ)大量文本內(nèi)容,還是使用 Text 更合適一些。
接下來(lái),我們需要在odoo.conf文件的addons_path中添加/Users/vitermo/odoo12/mymodels,vitermo是我們的電腦用戶名稱,mymodels是我們存放模塊的文件夾,可以根據(jù)自己的情況進(jìn)行修改。
接下來(lái)我們打開瀏覽器訪問(wèn) localhost:8069 然后用超級(jí)管理員帳號(hào)登錄(不記得了?帳號(hào)密碼都是 admin),登錄后在應(yīng)用列表頁(yè)面,將搜索框的 Apps 標(biāo)簽去掉,搜索關(guān)鍵詞 todo 找到我們剛創(chuàng)建的模塊,點(diǎn)擊 Install 按鈕安裝模塊。好了,你很快就會(huì)發(fā)現(xiàn),頁(yè)面又倒回了應(yīng)用列表頁(yè)面,如果我們?cè)俅伟辞懊娴牟襟E搜索我們的模塊,你會(huì)發(fā)現(xiàn)沒(méi)有了安裝按鈕,現(xiàn)在顯示的是 Installed 已安裝,除了這個(gè)變化外仿佛一切都沒(méi)發(fā)生過(guò),這是為什么呢?

因?yàn)槲覀儧](méi)有入口,找不到可以打開我們的 Todo 應(yīng)用的地方,接下來(lái)我們就一起創(chuàng)建第一個(gè)入口——菜單。
創(chuàng)建菜單
光有模型是當(dāng)然不夠的,就好象一幢大樓,鋼筋骨架都搭起來(lái)了,然后把墻給封死了,沒(méi)有門我們進(jìn)不去呀!

剛好像說(shuō)了個(gè)不怎么恰當(dāng)?shù)谋扔?,不如直接?dòng)手,創(chuàng)建一個(gè)菜單更實(shí)際。在模塊里的 views 目錄下創(chuàng)建一個(gè) menus.xml 文件,然后輸入以下內(nèi)容:

<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <data>
        <!-- 主菜單定義 -->
        <menuitem id="menu_todo" name="Todo"/>
        <!-- 菜單動(dòng)作定義 -->
        <record id="action_todo_task" model="ir.actions.act_window">
            <field name="name">待辦事項(xiàng)</field>
            <field name="res_model">todo.task</field>
            <field name="view_type">form</field>
            <field name="view_mode">tree,form</field>
            <field name="target">current</field>
        </record>
        <!-- 子菜單定義 -->
        <menuitem action="action_todo_task" id="submenu_todo_task" name="待辦事項(xiàng)"
                  parent="menu_todo" sequence="10"/>
    </data>
</odoo>

上面各部分內(nèi)容我都寫上了備注,大家一看就應(yīng)該知道它們各自是干什么的了。在 Odoo中定義一個(gè)菜單,使用的是 menuitem,然后我們需要為菜單指定屬性 idname,前者是這個(gè)菜單的唯一標(biāo)識(shí),而后者則是這個(gè)菜單所顯示的名字。

然后我們定義了一個(gè)菜單動(dòng)作,也就是點(diǎn)擊一個(gè)菜單時(shí)所要執(zhí)行的動(dòng)作,Odoo 中動(dòng)作的類型分為幾個(gè)類型,從 model 這個(gè)屬性可以看出來(lái)一個(gè)動(dòng)作是屬于什么類型的,act_window表示我們定義的這個(gè)動(dòng)作是和窗口有關(guān)的,例如打開一個(gè)彈窗或者一個(gè)列表頁(yè)面,都可以通過(guò)窗口動(dòng)作實(shí)現(xiàn)。其他類型的動(dòng)作我們先放一放,后面會(huì)有專門的一篇文章用于講述動(dòng)作相關(guān)的內(nèi)容,我們先簡(jiǎn)單地了解一下定義一個(gè)窗口動(dòng)作有哪些要素。

和定義菜單一樣,必不可少的會(huì)有 id 這一屬性,以后我們將默認(rèn)所有在 .xml文件中定義的數(shù)據(jù),都需要帶有 id 屬性,畢竟這是我們能夠通過(guò)代碼找到它們的唯一標(biāo)識(shí)了。這里我們用了 record 標(biāo)簽,包裹了一系列的 field 來(lái)定義我們的動(dòng)作,除了可以定義動(dòng)作外,包括前面提到的菜單在內(nèi)的一切具有實(shí)際模型的對(duì)應(yīng)的數(shù)據(jù),我們都可以這樣定義,最大的區(qū)別就在于 model這個(gè)屬性所指定的值,它對(duì)應(yīng)到我們定義的數(shù)據(jù)是來(lái)自哪個(gè)模型的,被包裹在里面的 field 則對(duì)應(yīng)到一個(gè)模型的各個(gè)字段。剛開始可能不太明白,不過(guò)不要緊,后面會(huì)一直使用到,很快就能掌握的了。

最后我們定義了一個(gè)子菜單,可以看到和最開始定義的菜單不一樣的是,我們這里多了 3 個(gè)屬性,分別是 action、parentsequence。其中 action 的值是我們定義的動(dòng)作的id,表示點(diǎn)擊這個(gè)菜單,就執(zhí)行對(duì)應(yīng) id 的動(dòng)作,parent指定的值是我們定義的第一個(gè)菜單的 id,表示當(dāng)前菜單是指定菜單的子菜單,sequence 用于指定當(dāng)前菜單的位置,如果我們?cè)谥鞑藛蜗掠卸鄠€(gè)子菜單,我們可以通過(guò)這個(gè)屬性去指定各個(gè)子菜單排列的先后順序。

關(guān)于菜單和動(dòng)作,暫時(shí)就先到這里,最后不要忘了把文件 menus.xml放到__manifest__.pydata 列表中,不然我們定義的內(nèi)容是不會(huì)被加載的哦:

# 現(xiàn)在應(yīng)該是這樣的
'data': [
    #'security/ir.model.access.csv',
    'views/views.xml',
    'views/templates.xml',
    'views/menus.xml',
],

#'security/ir.model.access.csv',,注釋去掉,并且進(jìn)入到security/ir.model.access這個(gè)文件中,將其修改成如下圖:

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_todo_task,todo.task,model_todo_task,,1,1,1,1

后面幾個(gè)數(shù)字是權(quán)限的一些東西,目前我不知道怎么用,索性我全部都給你。
好咧,菜單有了,也就有了入口,現(xiàn)在我們刷新頁(yè)面看看有沒(méi)有什么變化,好像還是一樣沒(méi)有什么不一樣?當(dāng)然了,因?yàn)槲覀冃薷牧四K里的文件內(nèi)容,這些變動(dòng)并沒(méi)有被加載,所以我們需要先升級(jí)模塊。一樣的步驟,先找到我們的 Todo 應(yīng)用模塊,然后點(diǎn)擊卡片進(jìn)入表單頁(yè)面,可以看到有個(gè) Upgrade(升級(jí)) 按鈕,我們點(diǎn)擊這個(gè)按鈕把模塊升級(jí)一下,然后你就會(huì)發(fā)現(xiàn),我們終于看到了期待已久的菜單和 Todo 應(yīng)用的列表頁(yè)面啦~

屏幕快照 2018-12-30 上午12.50.58.png

各位可以創(chuàng)建自己的數(shù)據(jù)來(lái),頁(yè)面展示的是本人創(chuàng)建的數(shù)據(jù)
還記得在創(chuàng)建模型的時(shí)候給字段 name 加上了一個(gè) required=True 的屬性嗎?在創(chuàng)建記錄的表單頁(yè)我們可以看到,這個(gè)字段是淡紫色背景的,這說(shuō)明這一項(xiàng)是必填的內(nèi)容,如果不填寫,點(diǎn)擊 Save(保存) 按鈕,就會(huì)發(fā)現(xiàn)標(biāo)簽顯示的「描述」變成了紅色,輸入框也被紅色邊框包裹起來(lái)了,并且可以看到在窗口右上角出現(xiàn)了一個(gè)警告提示。
在創(chuàng)建好一條待辦事項(xiàng)的記錄后,點(diǎn)擊 Save 保存,如果想要繼續(xù)創(chuàng)建,可以直接在表單頁(yè)上點(diǎn)擊 Create 繼續(xù)創(chuàng)建新的記錄,也可以返回列表頁(yè)查看全部的待辦事項(xiàng)記錄。如果完成了一個(gè)待辦事項(xiàng),我們點(diǎn)擊對(duì)應(yīng)的記錄,進(jìn)入到表單頁(yè)面,然后點(diǎn)擊 Edit 編輯按鈕,然后勾選「已完成?」表示我們已經(jīng)完成了這個(gè)任務(wù)。

想要?jiǎng)h除掉一些記錄該怎么辦?可以在列表頁(yè)先勾選需要?jiǎng)h除的記錄,然后點(diǎn)擊上面的 Action 菜單,可以看到 Delete這個(gè)選項(xiàng),點(diǎn)擊后會(huì)詢問(wèn)是否要?jiǎng)h除,點(diǎn)擊 Ok 確認(rèn)就可以刪除啦~除了列表頁(yè)上可以刪除記錄,還能打開一條待辦事項(xiàng)進(jìn)入表單頁(yè)面,然后打開 Action 菜單執(zhí)行刪除操作

創(chuàng)建視圖
在創(chuàng)建菜單之后,我們直接就看到了相應(yīng)的列表和表單頁(yè)面,可是我們并沒(méi)有創(chuàng)建任何相關(guān)的內(nèi)容,這是 Odoo 自動(dòng)幫我們做了處理。如果一個(gè)模型沒(méi)有創(chuàng)建對(duì)應(yīng)的視圖(View),Odoo 就會(huì)根據(jù)默認(rèn)的規(guī)則進(jìn)行顯示。

可是默認(rèn)在列表頁(yè)只顯示了一個(gè) name字段,我們想要知道一個(gè)事項(xiàng)是否完成了,并不能直接在列表頁(yè)上知道,需要一個(gè)個(gè)點(diǎn)擊進(jìn)去查看,如果有很多的記錄,這可就太蛋疼了!所以我們還是需要自己創(chuàng)建一個(gè)列表視圖,把是否已完成顯示在列表頁(yè)上。

打開 views/views.xml,把里面注釋掉的內(nèi)容都刪掉,然后添加以下內(nèi)容:

<odoo>
    <data>
        <record id="todo_task_view_tree" model="ir.ui.view">
            <field name="name">todo.task.view_tree</field>
            <field name="model">todo.task</field>
            <field name="type">tree</field>
            <field name="arch" type="xml">
                <tree string="Todo">
                    <field name="name"/>
                    <field name="is_done"/>
                </tree>
            </field>
        </record>
    </data>
</odoo>

創(chuàng)建視圖相關(guān)的內(nèi)容,我們需要指定屬性 model="ir.ui.view",然后還有兩個(gè)關(guān)鍵的地方是 type 的值,如果創(chuàng)建的是列表視圖,則填寫 tree,如果是表單視圖則是form,除了這兩種視圖外還有其他類型的視圖,我們暫時(shí)不會(huì)接觸到。然后是 arch 的值,里面的內(nèi)容決定了我們的視圖長(zhǎng)什么樣,列表視圖需要用 <tree></tree>包裹起來(lái),表單視圖則是 <form></form>,包裹的內(nèi)容具會(huì)有所不同,這里我們只需要在列表視圖中將要顯示的字段列舉出來(lái)即可。

完成這一切之后,升級(jí)一下模塊,然后看看效果如何。
image.png

可以看到列表里多了一列「已完成?」,這樣我們就可以一目了然,知道哪些事項(xiàng)是已經(jīng)完成了的,然后就可以直接勾選將他們刪除掉啦 XD

本文大量摘抄odoo基礎(chǔ)教程,如若原作者不同意請(qǐng)聯(lián)系本人,本人立馬刪除該文章。同時(shí),本人推薦各位同學(xué)可以去原作者的文章進(jìn)行學(xué)習(xí),本文只是個(gè)人在學(xué)習(xí)odoo時(shí)的記錄,以便后續(xù)查看。如有對(duì)原作者損害,實(shí)屬抱歉。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容