Odoo中如何在XML文件使用不存储至数据库的计算字段
问题描述
我已经通过以下代码继承ir.model并创建了一个不存储到数据库的计算字段:
from odoo import api, fields, models, _ from odoo.http import request class ir_models(models.Model): _inherit = 'ir.model' website_models = fields.Boolean('Allowed Website Model', compute='_is_website_models') @api.depends('website_models') def _is_website_models(self): for models in self: fields = request.env['ir.model.fields'].search([('model_id', '=', models.id)]) for field in fields: if field.name == 'website_url': models.website_models = True else: models.website_models = False
现在想咨询:在Odoo中,如何在XML文件中使用这类不存储到数据库的计算字段?
解决方案
嘿,其实Odoo里非存储的计算字段(默认store=False)虽然没存在数据库里,但只要计算逻辑没问题,在XML视图和动作里的用法和普通字段差不太多,下面分几个常见场景给你说明:
1. 在视图里直接显示字段
最简单的用法就是把它加到树视图或表单视图里,和普通存储字段完全一样。比如给ir.model的树视图加这个字段:
<record id="view_ir_model_tree_website_inherit" model="ir.ui.view"> <field name="name">ir.model.tree.website.inherit</field> <field name="model">ir.model</field> <field name="inherit_id" ref="base.view_ir_model_tree"/> <field name="arch" type="xml"> <field name="name" position="after"> <field name="website_models" string="Allowed for Website"/> </field> </field> </record>
这样打开模型列表时,就能看到这个字段的布尔值了,系统会实时计算并显示。
2. 用做域条件过滤记录
你也可以用这个计算字段来过滤视图或动作里的记录,比如只显示那些有website_url字段的模型。不过要注意:非存储字段的域过滤是实时计算的,没法利用数据库索引,数据量大的时候可能会有点慢,小数据集完全没问题。
比如创建一个只显示允许网站模型的动作:
<record id="action_allowed_website_models" model="ir.actions.act_window"> <field name="name">Website Allowed Models</field> <field name="res_model">ir.model</field> <field name="view_mode">tree,form</field> <field name="domain">[('website_models', '=', True)]</field> </record>
或者直接给现有视图加默认过滤:
<record id="view_ir_model_tree_website_filter" model="ir.ui.view"> <field name="name">ir.model.tree.website.filter</field> <field name="model">ir.model</field> <field name="inherit_id" ref="base.view_ir_model_tree"/> <field name="arch" type="xml"> <xpath expr="//tree" position="attributes"> <attribute name="domain">[('website_models', '=', True)]</attribute> </xpath> </field> </record>
3. 关于分组和排序的限制
这里要提个坑:非存储字段没法用于服务器端的分组或排序(比如给树视图加group_by="website_models"),因为Odoo需要从数据库里取分组数据,而这个字段根本没存在库里。如果一定要做客户端分组,体验和性能都不太好,不建议这么用。
顺便给你的代码提个小优化
你的计算方法有两个小问题:
@api.depends('website_models')是错的,这个字段是计算出来的,不能依赖自己。应该依赖模型的字段集合,改成@api.depends('field_ids.name'),这样当模型的字段变化时,计算字段会自动更新。- 循环所有字段的写法效率不高,而且逻辑有问题(最后一个字段不是
website_url的话会覆盖成False),可以改成更简洁高效的写法:
@api.depends('field_ids.name') def _is_website_models(self): for model in self: # 直接判断是否存在website_url字段 model.website_models = any(field.name == 'website_url' for field in model.field_ids)
另外,request.env在非HTTP场景(比如定时任务)下会报错,建议改成self.env,兼容性更好。
内容的提问来源于stack exchange,提问作者Avani Somaiya
相关产品推荐
相关产品推荐

