Search 1.9 billion lines of Odoo code on GitHub

demo_hierarchy_tutorial

Author: My Company
License: no license
Branch: 14.0
Repository: twtrubiks/odoo-demo-addons-tutorial
Dependencies: base
Languages: Markdown (137, 54.8%), Python (30, 12.0%), and XML (83, 33.2%)
Other branches: master

<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 = &#39;demo.hierarchy&#39; _description = &#39;Demo Hierarchy Tutorial&#39;</p> <pre><code>name = fields.Char(string=&#39;name&#39;, index=True) parent_id = fields.Many2one(&#39;demo.hierarchy&#39;, string=&#39;Related Partner&#39;, index=True) parent_name = fields.Char(related=&#39;parent_id.name&#39;, readonly=True, string=&#39;Parent name&#39;) child_ids = fields.One2many(&#39;demo.hierarchy&#39;, &#39;parent_id&#39;, string=&#39;Contacts&#39;, domain=[(&#39;active&#39;, &#39;=&#39;, 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 &lt;record id=&quot;view_form_demo_hierarchy&quot; model=&quot;ir.ui.view&quot;&gt; &lt;field name=&quot;name&quot;&gt;Demo Hierarchy Form&lt;/field&gt; &lt;field name=&quot;model&quot;&gt;demo.hierarchy&lt;/field&gt; &lt;field name=&quot;arch&quot; type=&quot;xml&quot;&gt; &lt;form string=&quot;Demo Hierarchy&quot;&gt; &lt;sheet&gt; &lt;group&gt; &lt;field name=&quot;name&quot;/&gt; &lt;field name=&quot;active&quot;/&gt; &lt;field name=&quot;parent_id&quot;/&gt; &lt;field name=&quot;parent_name&quot;/&gt; &lt;/group&gt; &lt;notebook&gt; &lt;page string=&quot;Hierarchy&quot;&gt; &lt;field name=&quot;child_ids&quot; mode=&quot;kanban&quot;&gt; &lt;form string=&quot;Contact / Address&quot;&gt; &lt;sheet&gt; &lt;field name=&quot;parent_id&quot; invisible=&quot;1&quot;/&gt; &lt;hr/&gt; &lt;group&gt; &lt;field name=&quot;name&quot; string=&quot;Contact Name&quot;/&gt; &lt;/group&gt; &lt;/sheet&gt; &lt;/form&gt; &lt;/field&gt; &lt;/page&gt; &lt;/notebook&gt; &lt;/sheet&gt; &lt;/form&gt; &lt;/field&gt; &lt;/record&gt; </code></p> <p>寫法和一般的 Many2one 或 One2many 是一樣的, 然後在 One2many 裡面,</p> <p>將 <code>parent_id</code> 隱藏起來, 因為不需要.</p> <p><code>&lt;field name=&quot;parent_id&quot; invisible=&quot;1&quot;/&gt;</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 = &#39;Contact&#39; _inherit = [&#39;format.address.mixin&#39;] _name = &quot;res.partner&quot; _order = &quot;display</em>name&quot;</p> <pre><code>...... parent_id = fields.Many2one(&#39;res.partner&#39;, string=&#39;Related Company&#39;, index=True) parent_name = fields.Char(related=&#39;parent_id.name&#39;, readonly=True, string=&#39;Parent name&#39;) child_ids = fields.One2many(&#39;res.partner&#39;, &#39;parent_id&#39;, string=&#39;Contacts&#39;, domain=[(&#39;active&#39;, &#39;=&#39;, True)]) ref = fields.Char(string=&#39;Internal Reference&#39;, 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[&#39;res.partner&#39;].search([(&#39;id&#39;, &#39;child_of&#39;, 14)]) #(小技巧, 從後面看回來, 14 的孩子) res.partner(14, 26, 33, 27, 68) ```</p> </blockquote> </blockquote> </blockquote> <p>```python</p> <blockquote> <blockquote> <blockquote> <p>self.env[&#39;res.partner&#39;].search([(&#39;id&#39;, &#39;child_of&#39;, [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[&#39;res.partner&#39;].search([(&#39;id&#39;, &#39;child_of&#39;, [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[&#39;res.partner&#39;].search([(&#39;id&#39;, &#39;parent_of&#39;, 68)]) #(小技巧, 從後面看回來, 68 的父親) res.partner(14, 68, 26) ```</p> </blockquote> </blockquote> </blockquote> <p>在 odoo 原始碼中, 可能會看到以下的 code</p> <p><code>(&#39;company_id&#39;,&#39;child_of&#39;,[user.company_id.id])]</code></p> <p>問題點在於為甚麼要別使用 <code>[]</code></p> <p>我這邊猜測應該是為了要避免 WARNING</p> <p>```python</p> <blockquote> <blockquote> <blockquote> <p>self.env[&#39;res.partner&#39;].search([(&#39;id&#39;, &#39;parent<em>of&#39;, [False])]) res.partner() self.env[&#39;res.partner&#39;].search([(&#39;id&#39;, &#39;parent</em>of&#39;, False)]) # 會有 WARNING 2020-07-29 WARNING odoo919 odoo.osv.expression: Unexpected domain [(&#39;id&#39;, &#39;parent_of&#39;, False)], interpreted as False res.partner() ```</p> </blockquote> </blockquote> </blockquote>