มาสร้าง View ที่ไม่ใช่ Views ใน Odoo กันเถอะ

ทุกคนน่าจะคุ้นเคยกับ Views ใน Odoo กันอยู่บ้าง หลังจากที่เราเพิ่มหรือลด field ใน Odoo เสร็จแล้ว ส่วนต่อไปก็คงหนีไม่พ้นการจัดการ การแสดงผลบนหน้าจอของผู้ใช้งานนั้นเอง ซึ่งใน Odoo ทั้งหมด จะทำผ่าน Views แต่นั่นไม่ใช่ View ที่เราจะพูดถึงกันวันนี้นะ
18 กรกฎาคม ค.ศ. 2022 โดย
Administrator

View ที่สร้างจาก Odoo

Prologue

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

ปกติเวลาเราสร้าง models ขึ้นมาใน odoo โดยการ inherit มาจาก class models ตัว odoo จะนำข้อมูลต่าง ๆตัวอย่างการสร้าง 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 ที่เห็นได้ชัดก็คือ

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

อดีของ 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_idorder 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

หลังจากที่เรา Install หรือ Update Module นี้แล้ว ก็จะเป็น view ปรากฎใน DatabaseViews: stock_invoice_ref ที่เราสร้างจาก Odoo

Nothing Special :)

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

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

Administrator 18 กรกฎาคม ค.ศ. 2022
แชร์โพสต์นี้
แท็ก