View ที่สร้างจาก Odoo
วันนี้เราจะมาเรียนรู้ View ที่ไม่ใช่ Views กัน
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_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 อย่างครับ
เช็คก่อนครับว่าถ้ามี 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<'