【ODOO】如何使用search查询匹配多个属性值的产品记录

有这么些个数据模型结构,产品product.template模型下,有One2many类型字段attribute_line_ids指向product.attribute.line数据模型,在product.attribute.line数据模型中,有Many2one字段 product_id指回 product.template模型,还有Many2one字段attribute_id指向product.attribute数据模型,还有Many2many类型字段attribute_value_ids指向product.attribute.value模型。如下:

class ProductTemplate(models.Model):
    _name = "product.template"
    
    name = fields.Char(string="Name")
    attribute_line_ids = fields.One2many("product.attribute.line",string="Attributes")

class ProductAttributeLine(models.Model):
    _name = "product.attribute.line"
    
    product_id = fields.Many2one('product.template', string='Product ID')
    attribute_id = fields.Many2one('product.attribute', string="Attr Name")
    attribute_value_ids = fields.Many2many('product.attribute.value', string="Attr Values")

class ProductAttribute(models.Model):
    _name = "product.attribute"

    name = fields.Char('Name', required=True, translate=True)
    value_ids = fields.One2many('product.attribute.value', 'attribute_id', 'Values', copy=True)
    attribute_line_ids = fields.One2many('product.attribute.line', 'attribute_id', 'Lines')

class ProductAttributeValue(models.Model):
    _name = "product.attribute.value"

    name = fields.Char('Value', required=True, translate=True)
    attribute_id = fields.Many2one('product.attribute', 'Attribute', ondelete='cascade', required=True)

创建产品及增加属性,得到3个产品

产品名(name)测试1 
属性明细(attribute_line_ids )属性名(attribute_id.name )属性值(attribute_line_ids.name)
 外壳颜色红色/白色(两个值)
 底壳颜色白色
 尺寸13寸
   
产品名(name)测试2 
属性明细(attribute_line_ids )属性名(attribute_id.name )属性值(attribute_line_ids.name)
 上壳颜色红色
 底壳颜色白色
 尺寸15寸
   
产品名(name)测试3 
属性明细(attribute_line_ids )属性名(attribute_id.name )属性值(attribute_line_ids.name)
 上壳颜色白色
 底壳颜色红色/白色(两个值)
 尺寸15寸

1 假如只知道要查询的产品有一个属性值是白色(不知道属性名是什么,只知道属性值是白色)

    obj = self.env["product.template"]
    domain = [("attribute_line_ids.attribute_value_ids.name","=","白色")]
    res = obj.sudo().search(domain)

这样,会查询出3条记录。

2 假如知道要查询的产品属性值既有红色,又有白色(还是不知道属性名是什么)

    obj = self.env["product.template"]
    domain = [
        ("attribute_line_ids.attribute_value_ids.name","=","红色"),             
        ("attribute_line_ids.attribute_value_ids.name","=","白色")
    ]
    res = obj.sudo().search(domain)

 这样查出来的记录仍会是3条。

3 假如知道要查询的产品属性值既有红色,又有白色(还是不知道属性名是什么),但还知道尺寸是15寸

    obj = self.env["product.template"]
    domain = [
        ("attribute_line_ids.attribute_value_ids.name","=","红色"),
        ("attribute_line_ids.attribute_value_ids.name","=","白色"),
        ("attribute_line_ids.attribute_value_ids.attribute_id.name","=","尺寸"),
        ("attribute_line_ids.attribute_value_ids.name","=","15寸")
    ]
    res = obj.sudo().search(domain)

这样就可以拿到 测试1 测试2 两条产品数据。

4 假如知道要查询的产品的底壳颜色只有白色,尺寸是13寸

    obj = self.env["product.template"]
    domain = [
        ("attribute_line_ids.attribute_id.attribute_value_ids.name","=","底壳颜色"),
        ("attribute_line_ids.attribute_value_ids.name","=","白色"),
        ("attribute_line_ids.attribute_value_ids.attribute_id.name","=","尺寸"),
        ("attribute_line_ids.attribute_value_ids.name","=","15寸")
    ]
    res = obj.sudo().search(domain)

很遗憾,这样并不能过滤出底壳颜色只有白色的13寸尺的产品。因为再M2M字段中,使用这种方式去过滤,并不严谨。当一条属性记录中的属性名为底壳颜色,但对应的属性值为 红色、白色 两条记录时。使用上面的代码,会将所有包含 底壳颜色=白色 的记录都拿到。只要 底壳颜色=白色 存在就行,其他你有什么我都不管,因为 底壳颜色=红色 和 底壳颜色=白色 是两条单独的数据。

那怎么办?再加一条 ("attribute_line_ids.attribute_line_ids.name","!=","红色") ?不要,这样解决不了上面说的问题,因为 底壳颜色 = 白色 已经满足了 ("attribute_line_ids.attribute_line_ids.name","=","白色") 条件,而且 底壳颜色 = 白色 也满足了 ("attribute_line_ids.attribute_line_ids.name","!=","红色") 的条件。

到底怎么办?如果非要使用这种过滤方式,我个人建议(因为我不知道其他的方式)按上面的代码先缩小搜索范围,然后对得到的结果数据集做一次filtered,对结果数据集进行二次过滤,就像下面这样:

    for item in res:
        if item.attribute_line_ids.filtered(lambda l: l.attribute_id.name == '底壳颜色' and len(l.attribute_line_ids) == 1 and l.attribute_line_ids.name == '白色'):
            # do something matched
            pass
        else:
            # do something un-matched
            pass

如发现问题,欢迎指正

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值