se adiciona notificaciones de cambios para fields.One2Many
FossilOrigin-Name: b422aa912c7c7873edcbbecf1914e9ff21a24cab3fc7e2a788e00efc16fe2f51
This commit is contained in:
		| @@ -1,11 +1,46 @@ | ||||
| from .field import Field | ||||
|  | ||||
| class BoundModel: | ||||
|     def __init__(self, creator): | ||||
| # TODO(bit4bit) lograr que isinstance se aplique | ||||
| # al objeto envuelto | ||||
| class _RelationProxy(): | ||||
|     def __init__(self, obj, inst, attribute): | ||||
|         self.__dict__['_obj'] = obj | ||||
|         self.__dict__['_inst'] = inst | ||||
|         self.__dict__['_attribute'] = attribute | ||||
|  | ||||
|     def __getattr__(self, name): | ||||
|         if (name in self.__dict__): | ||||
|             return self.__dict__[name] | ||||
|  | ||||
|         return getattr(self.__dict__['_obj'], name) | ||||
|  | ||||
|     def __setattr__(self, attr, value): | ||||
|         # TODO(bit4bit) hacemos proxy al sistema de notificacion de cambios | ||||
|         # algo burdo, se usa __dict__ para saltarnos el __getattr__ y generar un fallo por recursion | ||||
|         for fun in self.__dict__['_inst']._on_change_fields[self.__dict__['_attribute']]: | ||||
|             fun(self.__dict__['_inst'], self.__dict__['_attribute'], value) | ||||
|  | ||||
|         return setattr(self._obj, attr, value) | ||||
|  | ||||
| class _Relation(): | ||||
|     def __init__(self, creator, inst, attribute): | ||||
|         self.creator = creator | ||||
|         self.inst = inst | ||||
|         self.attribute = attribute | ||||
|         self.relations = [] | ||||
|  | ||||
|     def create(self): | ||||
|         return self.creator() | ||||
|         n_relations = len(self.relations) | ||||
|         attribute = '%s_%d' % (self.attribute, n_relations) | ||||
|         relation = self.creator(attribute) | ||||
|         proxy = _RelationProxy(relation, self.inst, self.attribute) | ||||
|  | ||||
|         self.relations.append(relation) | ||||
|         return proxy | ||||
|  | ||||
|     def __len__(self): | ||||
|         return len(self.relations) | ||||
|  | ||||
|  | ||||
| class One2Many(Field): | ||||
|     def __init__(self, model, name=None, namespace=None, default=None): | ||||
| @@ -13,13 +48,16 @@ class One2Many(Field): | ||||
|         self.field_name = name | ||||
|         self.namespace = namespace | ||||
|         self.default = default | ||||
|         self.count_relations = 0 | ||||
|         self.relation = None | ||||
|          | ||||
|     def __get__(self, inst, cls): | ||||
|         assert self.name is not None | ||||
|         def creator(): | ||||
|             attribute = '%s_%d' % (self.name, self.count_relations) | ||||
|             self.count_relations += 1 | ||||
|  | ||||
|         def creator(attribute): | ||||
|             return self._create_model(inst, name=self.field_name, model=self.model, attribute=attribute) | ||||
|          | ||||
|         return BoundModel(creator) | ||||
|         if self.relation: | ||||
|             return self.relation | ||||
|         else: | ||||
|             self.relation = _Relation(creator, inst, self.name) | ||||
|             return self.relation | ||||
|   | ||||
| @@ -416,3 +416,29 @@ def test_model_one2many(): | ||||
|     line = invoice.lines.create() | ||||
|     line.quantity = 5 | ||||
|     assert '<Invoice><Line quantity="3"/><Line quantity="5"/></Invoice>' == invoice.to_xml() | ||||
|  | ||||
|  | ||||
| def test_model_one2many_with_on_changes(): | ||||
|     class Line(facho.model.Model): | ||||
|         __name__ = 'Line' | ||||
|  | ||||
|         quantity = fields.Attribute('quantity') | ||||
|          | ||||
|     class Invoice(facho.model.Model): | ||||
|         __name__ = 'Invoice' | ||||
|  | ||||
|         lines = fields.One2Many(Line) | ||||
|         count = fields.Attribute('count', default=0) | ||||
|          | ||||
|         @fields.on_change(['lines']) | ||||
|         def refresh_count(self, name, value): | ||||
|             self.count = len(self.lines) | ||||
|  | ||||
|     invoice = Invoice() | ||||
|     line = invoice.lines.create() | ||||
|     line.quantity = 3 | ||||
|     line = invoice.lines.create() | ||||
|     line.quantity = 5 | ||||
|  | ||||
|     assert len(invoice.lines) == 2 | ||||
|     assert '<Invoice count="2"><Line quantity="3"/><Line quantity="5"/></Invoice>' == invoice.to_xml() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user