View ที่สร้างจาก Odoo
Prologue
โดยปกติเวลาเราสร้าง models ขึ้นมาใน odoo โดยการ inherit มาจาก class models ตัว odoo จะนำข้อมูลต่าง ๆ เช่น fields, constraint, index ไปสร้าง table ให้ด้วยชื่อที่เรากำหนดไว้ที่ class และเมื่อ odoo instance class เรียบร้อยแล้ว เราก็จะได้ ข้อมูลใน table นั้น ๆ ออกมา ซึ่งข้อมูลที่อยู่ในแต่ละ row ของ table เราจะเรียกว่า recordset
ตัวอย่างการสร้าง 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_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 อย่าง คือ
- เช็คก่อนว่าถ้ามี View นี้อยู่แล้ว ให้ทำการลบทิ้ง
- ใช้ create or replace สร้าง Query ของ View
- 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<'
มาสร้าง View ที่ไม่ใช่ Views ใน Odoo กันเถอะ