1. 使用 env.cr.execute
执行 SQL 语句
Odoo ORM 提供的 env.cr.execute()
可以直接执行 SQL 语句,这样可以在 Python 代码中调用 SQL 逻辑,结合 Odoo 的业务模型实现复杂的逻辑操作。execute()
方法适合处理批量数据更新、复杂查询等。
示例:批量更新 customer_id
字段
def update_customer_ids(self): query = """ UPDATE purchase_account_invoice AS pai SET customer_id = COALESCE( (SELECT delivery_order.customer_id FROM delivery_order WHERE delivery_order.id = pai.delivery_order_id), (SELECT purchase_order.customer_id FROM purchase_order WHERE purchase_order.id = pai.purchase_order) ) WHERE pai.delivery_order_id IS NOT NULL OR pai.purchase_order IS NOT NULL; """ self.env.cr.execute(query) self.env.cr.commit() # 提交更改
注意:SQL 操作后,可以用 invalidate_cache()
来刷新缓存,确保 ORM 缓存数据一致
2. 使用 SQL 函数实现数据聚合或计算
在 Odoo 中处理数据聚合、统计和复杂计算时,可以用 SQL 函数(如 SUM
、COUNT
、AVG
等)直接在数据库中完成计算,减少了 Python 循环操作,能大幅提高效率。
示例:统计每位客户的总订单金额
def get_total_order_amount_by_customer(self): query = """ SELECT partner_id, SUM(amount_total) FROM sale_order GROUP BY partner_id """ self.env.cr.execute(query) results = self.env.cr.fetchall() # 处理查询结果 for partner_id, total_amount in results: print(f"客户ID: {partner_id}, 总订单金额: {total_amount}")
3. 使用 env.cr.fetchall()
获取 SQL 查询结果
fetchall()
方法可以将 SQL 查询结果作为列表返回,适用于需要将查询结果进一步处理的情况。对于复杂的查询结构,fetchall()
提供了一个非常方便的方式将数据转化为 Python 可用的格式。
示例:筛选满足特定条件的订单
def get_filtered_orders(self): query = """ SELECT id, name, amount_total FROM sale_order WHERE state = 'sale' AND amount_total > 5000 """ self.env.cr.execute(query) results = self.env.cr.fetchall() return [{'id': row[0], 'name': row[1], 'amount_total': row[2]} for row in results]
4. 使用 WITH
语句和 SQL CTE(公用表表达式)
对于需要多层嵌套查询的复杂 SQL 逻辑,可以使用 WITH
语句创建临时表,然后在 Python 代码中使用 env.cr.execute()
来执行。CTE 非常适合处理复杂的条件筛选、分组和聚合查询。
示例:计算每月的销售总额
def get_monthly_sales(self): query = """ WITH monthly_sales AS ( SELECT DATE_TRUNC('month', order_date) AS month, SUM(amount_total) AS total FROM sale_order WHERE state = 'sale' GROUP BY DATE_TRUNC('month', order_date) ) SELECT month, total FROM monthly_sales ORDER BY month; """ self.env.cr.execute(query) results = self.env.cr.fetchall() return [{'month': row[0], 'total': row[1]} for row in results]
5. 使用 Odoo ORM 结合 SQL 优化批量操作
在某些情况下,将 Odoo ORM 的便利性和 SQL 的高效性结合使用,可以优化批量操作。比如在进行多条数据筛选和更新时,可以用 ORM 的 search
查找到所需的记录,然后用 SQL 批量更新,既保持了 ORM 的兼容性,也享受了 SQL 的效率。
示例:更新符合条件的记录,避免逐条写入
def update_large_records(self): record_ids = self.env['purchase.account.invoice'].search([]).ids if record_ids: query = """ UPDATE purchase_account_invoice SET customer_id = 1 -- 假设所有满足条件的记录的 customer_id 更新为 1 WHERE id = ANY(%s) """ self.env.cr.execute(query, (record_ids,)) self.env.cr.commit()
6. 在 @api.model
或 @api.multi
方法中结合 SQL 执行业务逻辑
在自定义模型方法中,可以使用 SQL 来执行业务逻辑,并返回结构化数据,进一步结合 ORM 实现功能。
示例:在自定义按钮操作中批量执行 SQL 操作
from odoo import models, api class PurchaseAccountInvoice(models.Model): _name = 'purchase.account.invoice' @api.multi def action_bulk_update(self): for record in self: query = """ UPDATE purchase_account_invoice SET customer_id = %s WHERE id = %s """ self.env.cr.execute(query, (record.new_customer_id, record.id)) self.env.cr.commit()
总结
env.cr.execute()
:在 Odoo 中执行 SQL 语句的核心方法,适用于批量操作和复杂查询。- 结合 SQL 函数:通过 SQL 中的聚合函数如
SUM
、COUNT
等,实现高效的数据统计。 fetchall()
返回结果:配合execute()
使用,将查询结果处理为 Python 的数据格式。WITH
语句和 CTE:用于多层嵌套查询和复杂的 SQL 逻辑处理。- SQL 和 ORM 结合:对于批量数据更新,将 Odoo ORM 的便利性和 SQL 的高效性结合,可以获得最佳性能。
这种结合 SQL 与 Python 代码的方式,不仅能提升代码效率,还能简化业务逻辑。
标签:Python,self,Odoo,order,env,SQL,cr,id From: https://www.cnblogs.com/lyt263/p/18517273