Hi all,
In continuation to the POC and the related discussions in IRC sometime back we
have a cleaner and flexible proposal.
This would mea that we have a new model class called ModelEAV which inherits
from ModelStorage and handles attributes.
It was easier to write some code to explain this rather than explain in English
so a rough code sketch of the same which was done is below:
This is not a final code but just to have a good understanding. Please do
review the idea.
Models:
ir.attribute - Where the attributes for a model are defined
========
model : fields.Many2one('ir.model')
name : fields.Char
type : fields.Selection(
[
text/selection/binary/numeric
]
)
selections : fields.One2Many ir.attribute.selections (try using property fields)
active: fields.Boolean
help: fields.Text
Ex:
model: `product.product`
name: `color`
type: `selection`
active: True
help: `Choose the color of the product`
ir.attribute.selections
==============
attribute : fields.Many2One ir.attribute
name : fields.Char
Ex:
attribute: `color` name: `Red`
attribute: `color` name: `Green`
attribute: `color` name: `Blue`
attribute: `color` name: `White`
ir.attribute.values - Where actual values would be stored
=============
entity : fields.Reference
attribute: fields.Many2One ir.attribute
value: base fields for storing value
value_text : Wrapper function field
value_selection : Wrapper function field
value_binary : Wrapper function field
value_numeric : Wrapper function field
New Model Abstraction called ModelEAV will be defined where the EAV pattern
needs to be used.
class ModelEAV(ModelStorage):
attribute_ = fields.One2Many('ir.attribute.values', None)
def create(self, values):
attribute_values_obj = self.pool.get('ir.attribute.values')
attributes = None
if 'attributes_' in values.keys():
attributes = values.pop('attributes_')
res = super(ModelEAV, self).create(values)
if attributes:
entity = '%s, %s' % (self._name, res)
for attribute_values in attributes:
attribute_values['entity'] = entity
attribute_values_obj.create(attribute_values)
return res
def write(self, ids, values):
attribute_values_obj = self.pool.get('ir.attribute.values')
attributes=None
if 'attributes_' in values.keys():
attributes = values.pop('attributes_')
if attributes:
entity = '%s, %s' % (self._name, res)
for attribute_values in attributes:
#Check if attribute already exists
attribute_value_id = attribute_values_obj.search([
('attribute', '=', attribute_values['attribute']),
('entity', '=', entity)
]
if attribute_value_id:
attribute_values_obj.write(attribute_value_id,
attribute_values)
else:
attribute_values['entity'] = entity
attribute_values_obj.create(attribute_values)
return super(ModelEAV, self).write(ids, values)
def delete(ids):
attribute_values_obj = self.pool.get('ir.attribute.values')
if isinstance(ids, (int, long)):
ids = [ids]
attribute_value_ids = attribute_values_obj.search([('entity', '=',
entity)])
if attribute_value_ids:
attribute_values_obj.delete(attribute_value_ids)
return super(ModelEAV, self).delete(ids)
def _view_look_dom_arch(self, tree, type):
attribute_obj = self.pool.get('ir.attribute')
attribute_obj.convert_view(tree)
arch, fields = super(ModelEAV, self)._view_look_dom_arch(tree, type)
return arch, fields
def fields_get(self, fields_names=None):
res = super(ModelEAV, self).fields_get(fields_names)
if 'attribute_' in fields_names:
#update the one2many_list so that the attribute has a domain on
this model
return res
def read(self, ids, fields_names=None):
single_record = False
if isinstance(ids, (int, long)):
single_record = True
ids = [ids]
attribute_values_obj = self.pool.get('ir.attribute.values')
read_attributes = fields_names is None or False
if 'attributes_' in fields_names:
fields_names.pop('attributes_')
read_attributes = True
res = self.read(ids, fields_names)
if read_attributes:
for record in res:
entity = '%s, %s' %(self._name, record['id'])
record['attributes_'] = attribute_values_obj.search([('entity',
'=', entity)])
if single_record:
return res[0]
return res
===============================
So for product.product to use EAV pattern:
from trytond.model import ModelSQL, ModelView, ModelEAV
class ProductProduct(ModelEAV, ModelSQL, ModelView):
_name = 'product.product'
regular fields
ProductProduct()
and update the view to use a new tag <attributes />
which will expand into a one2many list view where the attributes are
shown/edited.
Thanks,
Sharoon Thomas
On 20 Aug 2010, at 01:53, Phillip Heller wrote:
> Ok, so the Attributes you list below are perfect examples, and I do agree
> that Serial Numbers and other *instance* related values are a function of
> inventory.
>
> I suppose this concept is something to propose in a stock_instance module or
> something of the sort.
>
> Thanks.
>
> --phil
>
> On Aug 19, 2010, at 10:46 AM, Sharoon Thomas wrote:
>
> <snip>
>
>> Well i dont think that this EAV model would fit this purpose of a serial
>> number. However, in other terms this could be generalised. let me stick to
>> the example of mac book.
>>
>> Attributes could be:
>>
>> Screen Size
>> Weight
>> Processor
>> Memory
>> HDD
>>
>> etc. which remain constant for a product. having a different serial number,
>> I am not sure is an attribute issue. I think its more of an inventory
>> tracking issue ?
>
--
[email protected] mailing list