运用插入 many2many 属性的字段
- 
这是我要用到的模块 
 sale_product_multistep_configurator.zip
 product_variant_multi.zip
 product_variant_configurator.zip在addon/product_variant_multi/product_variant.py 的varants[code] _columns = { 
 'dimension_value_ids': fields.many2many('product.variant.dimension.value', 'product_product_dimension_rel', 'product_id','dimension_id', 'Dimensions', domain="[('product_tmpl_id','=',product_tmpl_id)]"),
 'variants': fields.function(_variant_name_get, method=True, type='char', size=64, string='Variants', readonly=True,
 store=
 'product.variant.dimension.type': (_get_products_from_dimension, None, 10),
 'product.product': (_get_products_from_product, None, 10),
 }[/code]但是他是一个many2many的属性,使用XML-RPC就不知道如何插入这类型的属性。望各位能指点迷津。
 谢谢大家。[[i] 本帖最后由 popkar77 于 2009-8-5 08:48 编辑 [/i]] 
- 
我看代码的时候不是太明白many2many field的store是怎么使用的。[code] 
 def _get_products_from_dimension(self, cr, uid, ids, context={}):
 result = []
 for type in self.pool.get('product.variant.dimension.type').browse(cr, uid, ids, context=context):
 for product_id in type.product_tmpl_id.variant_ids:
 result.append(product_id.id)
 return resultdef _get_products_from_product(self, cr, uid, ids, context={}): 
 result = []
 for product in self.pool.get('product.product').browse(cr, uid, ids, context=context):
 for product_id in product.product_tmpl_id.variant_ids:
 result.append(product_id.id)
 return result
 ..............................
 'variants': fields.function(_variant_name_get, method=True, type='char', size=64, string='Variants', readonly=True,
 store=
 'product.variant.dimension.type': (_get_products_from_dimension, None, 10),
 'product.product': (_get_products_from_product, None, 10),[/code] 在product.product里面字段是这样 
 [attach]209[/attach]
 但是我使用XML-RPC向variants插入字符串却没有反应,既没有报错,也没有插入成功[[i] 本帖最后由 popkar77 于 2009-8-6 09:35 编辑 [/i]] 
- 
确实看不太明白你的问题。 你为什么认为variant字段是many2many字段? variant字段是一个函数字段(fields.function), 其返回的数据类型是'char'。[code]'variants': fields.function(_variant_name_get, method=True, type='char', size=64, string='Variants', readonly=True, 
 store= {
 'product.variant.dimension.type': (_get_products_from_dimension, None, 10),
 'product.product': (_get_products_from_product, None, 10),
 }[/code]其中store参数的格式为:store={‘object_name’: (function_name,[‘field_name1’,’field_name2’],priority)}是当object_name的field_name1, field_name2 ...发生变化时调用function_name,并将返回的值作为函数字段的对应函数(本例中即:_variant_name_get)的运行参数。 这个字段的值实际上是计算出来的,并不是你可以直接写进去的。 [[i] 本帖最后由 digitalsatori 于 2010-3-10 19:04 编辑 [/i]] 
- 
先谢谢版主回复... 
 啊...是我笔误写错了,是function fields字段。
 现在我的想法是这样的通过其他的程序,读入一些product的variants名字,导入去openerp里面,所以想通过xml-rpc对里面的variants进行修改,您说variants是经过计算出来?也就是我直接插入是没有效果的?
 我所讲得的many2many关系是[code]
 'dimension_value_ids': fields.many2many('product.variant.dimension.value', 'product_product_dimension_rel', 'product_id','dimension_id', 'Dimensions', domain="[('product_tmpl_id','=',product_tmpl_id)]"),
 [/code]它使用到了一个关联表,而我不知道应该使用XML-RPC对这个关联表进行插入。
 完整代码:[code]from osv import fields, osvDimensions Definitionclass product_variant_dimension_type(osv.osv): 
 _name = "product.variant.dimension.type"
 _description = "Dimension Type"_columns = { 
 'name' : fields.char('Dimension', size=64),
 'sequence' : fields.integer('Sequence', help="The product 'variants' code will use this to order the dimension values"),
 'value_ids' : fields.one2many('product.variant.dimension.value', 'dimension_id', 'Dimension Values'),
 'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True, ondelete='cascade'),
 'allow_custom_value': fields.boolean('Allow Custom Value', help="If true, custom values can be entered in the product configurator"),
 }_order = "sequence, name" def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=None): 
 if context.get('product_tmpl_id', False):
 return super(product_variant_dimension_type, self).name_search(cr, user, '', args, 'ilike', None, None)
 else:
 return super(product_variant_dimension_type, self).name_search(cr, user, '', None, 'ilike', None, None)product_variant_dimension_type() class product_variant_dimension_value(osv.osv): 
 _name = "product.variant.dimension.value"
 _description = "Dimension Value"def _get_dimension_values(self, cr, uid, ids, context={}): 
 result = []
 for type in self.pool.get('product.variant.dimension.type').browse(cr, uid, ids, context=context):
 for value in type.value_ids:
 result.append(value.id)
 return result_columns = { 
 'name' : fields.char('Dimension Value', size=64, required=True),
 'sequence' : fields.integer('Sequence'),
 'price_extra' : fields.float('Price Extra', size=64),
 'price_margin' : fields.float('Price Margin', size=64), #TODO: this field is not implemented yet
 'dimension_id' : fields.many2one('product.variant.dimension.type', 'Dimension Type', required=True, ondelete='cascade'),
 'product_tmpl_id': fields.related('dimension_id', 'product_tmpl_id', type="many2one", relation="product.template", string="roduct Template", store=True),
 'dimension_sequence': fields.related('dimension_id', 'sequence', string="Related Dimension Sequence",#used for ordering purposes in the "variants"
 store={
 'product.variant.dimension.type': (_get_dimension_values, None, 10),
 }),
 }
 _order = "dimension_sequence, sequence, name"product_variant_dimension_value() class product_template(osv.osv): 
 _inherit = "product.template"_columns = { 
 'dimension_type_ids':fields.one2many('product.variant.dimension.type', 'product_tmpl_id', 'Dimension Types'),
 'variant_ids':fields.one2many('product.product', 'product_tmpl_id', 'Variants'),
 }def copy(self, cr, uid, id, default=None, context=None): 
 if default is None:
 default = {}
 default = default.copy()
 default.update({'variant_ids':False,})
 return super(product_template, self).copy(cr, uid, id, default, context)def button_generate_variants(self, cr, uid, ids, context={}): 
 def cartesian_product(args):
 if len(args) == 1: return [(x,) for x in args[0]]
 return [(i,) + j for j in cartesian_product(args[1:]) for i in args[0]]variants_obj = self.pool.get('product.product') 
 temp_type_list=[]
 temp_val_list=[]for product_temp in self.browse(cr, uid, ids, context): 
 for temp_type in product_temp.dimension_type_ids:
 temp_type_list.append(temp_type.id)
 temp_val_list.append([temp_type_value.id for temp_type_value in temp_type.value_ids])if last dimension_type has no dimension_value, we ignore itif not temp_val_list[-1]: 
 temp_val_list.pop()
 temp_type_list.pop()if temp_val_list: 
 list_of_variants = cartesian_product(temp_val_list)for variant in list_of_variants: 
 constraints_list=[('dimension_value_ids', 'in', ) for i in variant]prod_var=variants_obj.search(cr, uid, constraints_list) 
 if not prod_var:
 vals={}
 vals['product_tmpl_id']=product_temp.id
 vals['dimension_value_ids']=[(6,0,variant)]var_id=variants_obj.create(cr, uid, vals, {}) return True product_template() class product_product(osv.osv): 
 _inherit = "product.product"def _variant_name_get(self, cr, uid, ids, name, arg, context={}): 
 res = {}
 for product in self.browse(cr, uid, ids, context):
 r = map(lambda dim: (dim.dimension_id.name or '')+':'+(dim.name or '-'), product.dimension_value_ids)
 res[product.id] = ' - '.join(r)
 return resdef _get_products_from_dimension(self, cr, uid, ids, context={}): 
 result = []
 for type in self.pool.get('product.variant.dimension.type').browse(cr, uid, ids, context=context):
 for product_id in type.product_tmpl_id.variant_ids:
 result.append(product_id.id)
 return resultdef _get_products_from_product(self, cr, uid, ids, context={}): 
 result = []
 for product in self.pool.get('product.product').browse(cr, uid, ids, context=context):
 for product_id in product.product_tmpl_id.variant_ids:
 result.append(product_id.id)
 return resultdef _check_dimension_values(self, cr, uid, ids): # TODO: check that all dimension_types of the product_template have a corresponding dimension_value ?? 
 for p in self.browse(cr, uid, ids, {}):
 buffer = []
 for value in p.dimension_value_ids:
 buffer.append(value.dimension_id)
 unique_set = set(buffer)
 if len(unique_set) != len(buffer):
 return False
 return Truedef copy(self, cr, uid, id, default=None, context=None): 
 if default is None:
 default = {}
 default = default.copy()
 default.update({'variant_ids':False,})
 return super(product_product, self).copy(cr, uid, id, default, context)_columns = { 
 'dimension_value_ids': fields.many2many('product.variant.dimension.value', 'product_product_dimension_rel', 'product_id','dimension_id', 'Dimensions', domain="[('product_tmpl_id','=',product_tmpl_id)]"),
 'variants': fields.function(_variant_name_get, method=True, type='char', size=64, string='Variants', readonly=True,
 store=
 'product.variant.dimension.type': (_get_products_from_dimension, None, 10),
 'product.product': (_get_products_from_product, None, 10),
 }),
 }
 _constraints = [ (_check_dimension_values, 'Several dimension values for the same dimension type', ['dimension_value_ids']),]product_product()[/code]下面是图 
 [attach]210[/attach]版主所的说的计算应该就是,把下面选择好的dimension Value 存到Variants上面,我现在问题就是: 
 1.如何插入一个many2many的属性,也就是如何使用XML-RPC插入他们直接的关联表'product_product_dimension_rel‘。
 2.如果插入后,那个计算variants的方法会不会自动执行,因为根本目的我也是要改变variants的值。
 3.store那里的返回值我看到的是product.id。在_variant_name_get函数里面作为参数,是这里吗?[code]
 res[product.id] = ' - '.join(r)
 [/code][[i] 本帖最后由 popkar77 于 2009-8-6 16:02 编辑 [/i]] 
