Author: |
My Company |
License: |
no license |
Branch: |
master |
Repository: |
twtrubiks/odoo-demo-addons-tutorial |
Dependencies: |
base |
Languages: |
Markdown (137, 55.0%),
Python (30, 12.0%),
and
XML (82, 32.9%) |
Other branches: |
14.0 |
<h1>odoo hierarchy 實作</h1>
<p>建議觀看影片, 會更清楚:smile:</p>
<ul>
<li><p><a href="https://youtu.be/O_ch9553VQ0">Youtube Tutorial - odoo 手把手教學 hierarchy - part1</a> - <a href="https://github.com/twtrubiks/odoo-demo-addons-tutorial/tree/master/demo_hierarchy_tutorial#%E8%AA%AA%E6%98%8E">文章快速連結</a></p></li>
<li><p><a href="https://youtu.be/SER-ZVDnwGw">Youtube Tutorial - odoo 手把手教學 hierarchy - part2</a> - <a href="https://github.com/twtrubiks/odoo-demo-addons-tutorial/tree/master/demo_hierarchy_tutorial#%E8%AA%AA%E6%98%8E-child_of-%E5%92%8C-parent_of">文章快速連結</a></p></li>
</ul>
<p>建議在閱讀這篇文章之前, 請先確保了解看過以下的文章 (因為都有連貫的關係)</p>
<p><a href="https://github.com/twtrubiks/odoo-demo-addons-tutorial/tree/master/demo_odoo_tutorial">odoo 手把手建立第一個 addons</a></p>
<p>主要介紹 odoo 中如何實現 階層(hierarchy) 的關係.</p>
<h2>說明</h2>
<ul>
<li><a href="https://youtu.be/O_ch9553VQ0">Youtube Tutorial - odoo 手把手教學 hierarchy - part1</a></li>
</ul>
<p>之前不管是介紹 Many2one 還是 One2many, 都是對別的 model 產生關聯,</p>
<p>那有沒有和自己產生關聯的呢:smile:</p>
<ul>
<li><p><a href="https://github.com/twtrubiks/odoo-demo-addons-tutorial/tree/master/demo_expense_tutorial_v1#odoo-%E6%89%8B%E6%8A%8A%E6%89%8B%E6%95%99%E5%AD%B8---many2one---part1">odoo 手把手教學 - Many2one - part1</a></p></li>
<li><p><a href="https://github.com/twtrubiks/odoo-demo-addons-tutorial/tree/master/demo_expense_tutorial_v1#odoo-%E6%89%8B%E6%8A%8A%E6%89%8B%E6%95%99%E5%AD%B8---one2many---part3">odoo 手把手教學 - One2many - part3</a></p></li>
</ul>
<p>答案是有的哦, 就是 odoo 中的 階層(hierarchy) 的關係:satisfied:</p>
<p>階層(hierarchy) 的關係範例圖如下,</p>
<p><img src="https://i.imgur.com/jFmmet1.png" alt="alt tag"></p>
<p>接著來看教學的範例,</p>
<p><a href="models/models.py">models/models.py</a></p>
<p>```python
class DemoHierarchyTutorial(models.Model):
_name = 'demo.hierarchy'
_description = 'Demo Hierarchy Tutorial'</p>
<pre><code>name = fields.Char(string='name', index=True)
parent_id = fields.Many2one('demo.hierarchy', string='Related Partner', index=True)
parent_name = fields.Char(related='parent_id.name', readonly=True, string='Parent name')
child_ids = fields.One2many('demo.hierarchy', 'parent_id', string='Contacts', domain=[('active', '=', True)])
active = fields.Boolean(default=True)
</code></pre>
<p>```</p>
<p>比較特別的就是 <code>parent_id</code> 和 <code>child_ids</code> 都關聯到同一個 model (也就是自己本身 <code>demo.hierarchy</code>),</p>
<p>然後一個是 Many2one <code>parent_id</code> 和 One2many <code>child_ids</code>.</p>
<p><a href="views/view.xml">views/view.xml</a></p>
<p><code>xml
<record id="view_form_demo_hierarchy" model="ir.ui.view">
<field name="name">Demo Hierarchy Form</field>
<field name="model">demo.hierarchy</field>
<field name="arch" type="xml">
<form string="Demo Hierarchy">
<sheet>
<group>
<field name="name"/>
<field name="active"/>
<field name="parent_id"/>
<field name="parent_name"/>
</group>
<notebook>
<page string="Hierarchy">
<field name="child_ids" mode="kanban">
<form string="Contact / Address">
<sheet>
<field name="parent_id" invisible="1"/>
<hr/>
<group>
<field name="name" string="Contact Name"/>
</group>
</sheet>
</form>
</field>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
</code></p>
<p>寫法和一般的 Many2one 或 One2many 是一樣的, 然後在 One2many 裡面,</p>
<p>將 <code>parent_id</code> 隱藏起來, 因為不需要.</p>
<p><code><field name="parent_id" invisible="1"/></code></p>
<p>先來建立一比 <code>demo.hierarchy</code> (test1), <code>parent_id</code> 先不填</p>
<p><img src="https://i.imgur.com/sZGTOvZ.png" alt="alt tag"></p>
<p>點選 add 再建立一比 <code>demo.hierarchy</code> (test2)</p>
<p><img src="https://i.imgur.com/EfUkYeN.png" alt="alt tag"></p>
<p>呈現效果如下, test2 的 parent 就是 test1</p>
<p><img src="https://i.imgur.com/pHWlbU5.png" alt="alt tag"></p>
<p>點選 add 再建立一比 <code>demo.hierarchy</code> (test3),</p>
<p>呈現效果如下, test2 和 test1 的 parent 都是 test1</p>
<p><img src="https://i.imgur.com/yVhz0Be.png" alt="alt tag"></p>
<p>tree 的部份</p>
<p><img src="https://i.imgur.com/6Hsl2Gp.png" alt="alt tag"></p>
<p>db 中的狀態</p>
<p><img src="https://i.imgur.com/kuHStcy.png" alt="alt tag"></p>
<h2>說明 child<em>of 和 parent</em>of</h2>
<ul>
<li><a href="https://youtu.be/SER-ZVDnwGw">Youtube Tutorial - odoo 手把手教學 hierarchy - part2</a></li>
</ul>
<p>在 odoo 中很常看到 child<em>of 和 parent</em>of,</p>
<p>可以參考 Contact <code>res.partner</code>.</p>
<p>odoo 原始碼中的範例, 路徑 <code>odoo/addons/base/models/res_partner.py</code></p>
<p>```python
class Partner(models.Model):
<em>description = 'Contact'
_inherit = ['format.address.mixin']
_name = "res.partner"
_order = "display</em>name"</p>
<pre><code>......
parent_id = fields.Many2one('res.partner', string='Related Company', index=True)
parent_name = fields.Char(related='parent_id.name', readonly=True, string='Parent name')
child_ids = fields.One2many('res.partner', 'parent_id', string='Contacts', domain=[('active', '=', True)])
ref = fields.Char(string='Internal Reference', index=True)
......
</code></pre>
<p>```</p>
<p>其中 parent<em>id 是 Many2one 的關係 , 而 child</em>ids 則是 One2many的關係.</p>
<p>階層關係如下</p>
<p><img src="https://i.imgur.com/jFmmet1.png" alt="alt tag"></p>
<p>db 關係如下</p>
<p><img src="https://i.imgur.com/4TOjc8k.png" alt="alt tag"></p>
<p>階層關係如下</p>
<p><img src="https://i.imgur.com/cCAonbi.png" alt="alt tag"></p>
<p>db 關係如下</p>
<p><img src="https://i.imgur.com/FQ7s9C0.png" alt="alt tag"></p>
<p><code>child_of</code></p>
<p>```python</p>
<blockquote>
<blockquote>
<blockquote>
<p>self.env['res.partner'].search([('id', 'child_of', 14)]) #(小技巧, 從後面看回來, 14 的孩子)
res.partner(14, 26, 33, 27, 68)
```</p>
</blockquote>
</blockquote>
</blockquote>
<p>```python</p>
<blockquote>
<blockquote>
<blockquote>
<p>self.env['res.partner'].search([('id', 'child_of', [11])])
res.partner(11, 20, 22, 31, 23)
```</p>
</blockquote>
</blockquote>
</blockquote>
<p>child_of 也可以一次找多個</p>
<p>```python</p>
<blockquote>
<blockquote>
<blockquote>
<p>self.env['res.partner'].search([('id', 'child_of', [14, 11])])
res.partner(14, 26, 33, 27, 68......)
```</p>
</blockquote>
</blockquote>
</blockquote>
<p><code>parent_of</code></p>
<p>```python</p>
<blockquote>
<blockquote>
<blockquote>
<p>self.env['res.partner'].search([('id', 'parent_of', 68)]) #(小技巧, 從後面看回來, 68 的父親)
res.partner(14, 68, 26)
```</p>
</blockquote>
</blockquote>
</blockquote>
<p>在 odoo 原始碼中, 可能會看到以下的 code</p>
<p><code>('company_id','child_of',[user.company_id.id])]</code></p>
<p>問題點在於為甚麼要別使用 <code>[]</code></p>
<p>我這邊猜測應該是為了要避免 WARNING</p>
<p>```python</p>
<blockquote>
<blockquote>
<blockquote>
<p>self.env['res.partner'].search([('id', 'parent<em>of', [False])])
res.partner()
self.env['res.partner'].search([('id', 'parent</em>of', False)]) # 會有 WARNING
2020-07-29 WARNING odoo919 odoo.osv.expression: Unexpected domain [('id', 'parent_of', False)], interpreted as False
res.partner()
```</p>
</blockquote>
</blockquote>
</blockquote>