[Odoo] มาสร้าง View ที่ไม่ใช่ Views กันเถอะ
ทุกคนน่าจะคุ้นเคยกับ Views ใน odoo นะครับ เพราะหลังจากที่เราเพิ่มหรือลด field ใน odoo เสร็จแล้ว ส่วนต่อไปก็หนีไม่พ้นการจัดการ การแสดงผลบนหน้าจอของผู้ใช้งานนั้นเอง ซึ่งใน odoo ทั้งหมดจะทำผ่าน Views ครับ แต่นั่นไม่ใข่ View ที่เราพูดถึงกันวันนี้ครับ ;p
27 August, 2021 by
[Odoo] มาสร้าง View ที่ไม่ใช่ Views กันเถอะ
Tewtawat Chakrabandhu Na Ayutthaya (Off)
| No comments yet

 

View ที่สร้างจาก Odoo 
วันนี้เราจะมาเรียนรู้ View ที่ไม่ใช่ Views กัน

Prologue

         โดยปกติเวลาเราสร้าง models ขึ้นมาใน odoo โดยการ inherit มาจาก class models ตัว odoo จะนำข้อมูลต่างๆ เช่น fields, constraint, index ไปสร้าง table ให้ด้วยชื่อที่เรากำหนดไว้ที่ class และเมื่อ odoo instance class เรียบร้อยแล้ว เราก็จะได้ ข้อมูลใน table นั้นๆ ออกมาซึ่งข้อมูลที่อยู่ในแต่ละ row ของ table เราจะเรียกว่า recordset ครับ

ff

                             ตัวอย่างการสร้าง model โดยที่ฐานข้อมูลของเราจะได้ table ชื่อว่า product_principle

         ทีนี้ถ้าเราลองนึกถึงวิชา Database เมื่อเราพูดถึง table แล้ว แน่นอนก็จะมีอีกสิ่งนึงที่ตามมาเรียกได้ว่าเป็นคู่แท้กันเลยนั้นคือ View ครับ

What is a View ?

         View คือ Virtual table ที่เกิดจากผลลัพธ์ของการ Query ถูกใช้ในการดูข้อมูลหรือจัดการบางส่วนของ Table เท่านั้น ซึ่งตัว Column สามารถได้มาจากหลาย Table และข้อมูลในแต่ละ Column ก็จะเป็นข้อมูลที่มาจาก Table ของตัวเองอีกด้วย

Advantages over tables

         นอกจากจะใช้ซ่อนความโกลาหลของ Query ที่ไม่อยากให้ใครเห็นแล้ว ข้อดีของ View นั้นก็ยังมีอีกหลายข้อทีเดียว แต่ความน่าสนใจของ View ที่เห็นได้ชัดก็คือ

ไม่ใช้พื้นที่ในการจัดเก็บข้อมูลบนระบบของเรา

                                                    Ref. https://www.javatpoint.com/table-vs-view

         ทำให้เราอาจจะต้องพิจารณาถึงความเป็นไปได้ในการนำ View มาใช้เพิ่มมากขึ้น ทั้งนี้ก็แล้วแต่ สถานการณ์หรือความเหมาะสมของงานที่เรากำลังได้รับมอบหมายครับ

คำถามก็คือ...

แล้ว model ใน odoo ที่เราใช้เป็นตัวแทนของ table ต่างๆ มาตลอด สามารถเป็นตัวแทนของ View ได้หรือไม่ ?

คำตอบก็คือ...

ไม่ได้ครับ สวัสดีครับ -/\-” … หยอกก

จริงๆ แล้วคำถามไม่ใช่ ได้หรือไม่ แต่คือ ทำยังไงครับ ^^


First things first

Odoo ที่เราใช้ในวันนี้จะเป็น version 14 ครับ

         เนื่องจาก View เกิดจาก Query ให้เราลองสร้าง Query string ขึ้นมาชุดนึงครับ ซึ่ง table และ column ต่างๆ ต้องมีอยู่จริงบน database ด้วยครับ ด้านล่างเป็นตัวอย่างครับ

select    rel.picking_id                          as picking_id,
          string_agg(inv.name::text, ', '::text)  as invoice_number
from      account_move_stock_rel rel
left join account_move inv on inv.id = rel.account_move_id
group by  rel.picking_id
order by  rel.picking_id

จากนั้นให้ import tools ที่อยู่ใน module odoo มาก่อนครับ

from odoo import tools

ขั้นตอนต่อไปให้เราสร้าง models ขึ้นมา เหมือนกับที่เราสร้าง ใน Odoo ปกติได้เลยครับ

class StockInvoiceReference(models.Model):
    _name = 'stock.invoice.ref'
    _description = 'Stock Invoice Reference'


         เมื่อได้ class ที่เราต้องการแล้วให้เรา override method init (method นี้จะถูกเรียกทุกครั้ง หลังจาก ตัว models ทำการ เรียก method: _auto_init) โดยใส่ api model เป็น decorator ไว้ด้วยครับ

โดยสิ่งที่เราจะทำในนี้มี 3 อย่างครับ

  1. เช็คก่อนครับว่าถ้ามี View นี้อยู่แล้วให้ทำการลบทิ้ง

  2. ใช้ create or replace สร้าง Query ของ View

  3. Execute ผ่าน Cursor ของ Odoo

@api.model
def init(self):
    # Manipulate existing view
    tools.drop_view_if_exists(self.env.cr, self._table)

    # Logical Table Query
    query = """
        create or replace view %(view_name)s as (
            select  rel.picking_id                         as picking_id,
                    string_agg(inv.name::text, ', '::text) as invoice_number
            from    account_move_stock_rel rel
            left join account_move inv on inv.id = rel.account_move_id
            group by rel.picking_id
            order by rel.picking_id
        )
    """
    # Excute by Odoo Cursor Environment
    self.env.cr.execute(
        query, {
            'view_name': self._table
        }
    )

         สุดท้ายครับ กำหนดคุณสมบัติของ Fields ให้กับ Models ได้ตามปกติครับ โดยตั้งชื่อให้ตรงกับ ชื่อ Column ที่เราระบุไว้ใน View ครับ

picking_id = fields.Many2one(
    comodel_name='stock.picking',
    string='Stock Picking',
)

invoice_number = fields.Char(
    string='Invoice Reference.', 

)

และแล้ว เราก็จะได้ Models ที่เราสร้างจาก View จะมีหน้าตาประมาณนี้ครับ

# Import tools for drop_view_if_exists method
from odoo import tools
from odoo import models, fields, api


class StockInvoiceReference(models.Model):
    _name = 'stock.invoice.ref'
    _description = 'Stock Invoice Reference'
    _auto = False
    _rec_name = 'picking_id'
    _order = 'picking_id'

    picking_id = fields.Many2one(
        comodel_name='stock.picking',
        string='Stock Picking',
    )

    invoice_number = fields.Char(
        string='Invoice Reference.',
    )

    @api.model
    def init(self):
        # Manipulate existing view
        tools.drop_view_if_exists(self.env.cr, self._table)

        # Logical Table Query
        query = """
           create or replace view %(view_name)s as (
             select rel.picking_id                         as picking_id,
                    string_agg(inv.name::text, ', '::text) as invoice_number
             from   account_move_stock_rel rel
             left join account_move inv on inv.id = rel.account_move_id
             group by rel.picking_id
             order by rel.picking_id
        )
        """

        # Excute by Odoo Cursor Environment
        self.env.cr.execute(
            query, {
                'view_name': self._table
            }
        )


หลังจากที่เรา Install หรือ Update Module นี้แล้วก็จะเป็น view ปรากฎใน Database ครับ

                                                    Views: stock_invoice_ref ที่เราสร้างจาก Odoo

Nothing Special :)

         เสร็จแล้วครับ View ที่สร้างจาก Odoo เราสามารถนำไปใช้ใน Views เหมือน Models ปกติได้เลยครับ ไม่ว่าจะเป็น Tree, Pivot หรือ Graph ครับ รวมถึงความสามารถในการ Search หรือ Group by ก็ใช้ร่วมกับ view ได้เหมือนเป็น Table นึงเลยครับ

เป็นยังไงกันบ้าง ยากไหมครับ หวังว่าเพื่อนๆ จะทำกันได้นะครับ เจอกันใหม่บทความต่อไปครับผม >0<'

[Odoo] มาสร้าง View ที่ไม่ใช่ Views กันเถอะ
Tewtawat Chakrabandhu Na Ayutthaya (Off) 27 August, 2021
Share this post
Tags
Archive
Sign in to leave a comment