有这么些个数据模型结构,产品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
如发现问题,欢迎指正