se adiciona @fields.on_change para ejecutar funcion cuando se cambian los varoles de algun attributo
FossilOrigin-Name: bee19b201f8c1a6b972c2a9abfe5fb57a558a67be6ecddce4f7f07b5b6980215
This commit is contained in:
parent
b6219bd171
commit
c694603505
@ -1,4 +1,5 @@
|
||||
from .fields import Field
|
||||
from collections import defaultdict
|
||||
|
||||
class ModelMeta(type):
|
||||
def __new__(cls, name, bases, ns):
|
||||
@ -20,6 +21,19 @@ class ModelBase(object, metaclass=ModelMeta):
|
||||
obj._fields = {}
|
||||
obj._text = ""
|
||||
obj._namespace_prefix = None
|
||||
obj._on_change_fields = defaultdict(list)
|
||||
|
||||
def on_change_fields_for_function(function_name):
|
||||
# se recorre arbol buscando el primero
|
||||
for parent_cls in type(obj).__mro__:
|
||||
parent_meth = getattr(parent_cls, function_name, None)
|
||||
if not parent_meth:
|
||||
continue
|
||||
|
||||
on_changes = getattr(parent_meth, 'on_changes', None)
|
||||
if on_changes:
|
||||
return on_changes
|
||||
return []
|
||||
|
||||
# forzamos registros de campos al modelo
|
||||
# al instanciar
|
||||
@ -28,7 +42,12 @@ class ModelBase(object, metaclass=ModelMeta):
|
||||
if hasattr(v, 'default') and v.default is not None:
|
||||
setattr(obj, key, v.default)
|
||||
|
||||
|
||||
# register callbacks for changes
|
||||
function_name = 'on_change_%s' % (key)
|
||||
on_change_fields = on_change_fields_for_function(function_name)
|
||||
for field in on_change_fields:
|
||||
obj._on_change_fields[field].append(function_name)
|
||||
|
||||
return obj
|
||||
|
||||
def _set_attribute(self, field, name, value):
|
||||
|
@ -6,3 +6,15 @@ from .virtual import Virtual
|
||||
from .field import Field
|
||||
|
||||
__all__ = [Attribute, Many2One, Model, Virtual, Field]
|
||||
|
||||
def on_change(fields):
|
||||
from functools import wraps
|
||||
|
||||
def decorator(func):
|
||||
setattr(func, 'on_changes', fields)
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(self, *arg, **kwargs):
|
||||
return func(self, *arg, **kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
@ -16,4 +16,6 @@ class Attribute(Field):
|
||||
def __set__(self, inst, value):
|
||||
assert self.name is not None
|
||||
self.value = value
|
||||
|
||||
self._changed_field(inst, self.name, value)
|
||||
inst._set_attribute(self.name, self.attribute, value)
|
||||
|
@ -39,3 +39,8 @@ class Field:
|
||||
self._set_namespace(obj, self.namespace, inst.__namespace__)
|
||||
inst._fields[self.name] = obj
|
||||
return obj
|
||||
|
||||
def _changed_field(self, inst, name, value):
|
||||
for fun in inst._on_change_fields[name]:
|
||||
getattr(inst, fun)(name, value)
|
||||
|
||||
|
@ -31,4 +31,5 @@ class Function(Field):
|
||||
|
||||
def __set__(self, inst, value):
|
||||
inst._set_field(self.name, self.field)
|
||||
self._changed_field(inst, self.name, value)
|
||||
self.field.__set__(inst, value)
|
||||
|
@ -25,6 +25,7 @@ class Many2One(Field):
|
||||
setter(inst_model, value)
|
||||
else:
|
||||
inst_model._set_content(value)
|
||||
|
||||
|
||||
self._changed_field(inst, self.name, value)
|
||||
|
||||
|
||||
|
@ -364,3 +364,38 @@ def test_field_inserted_default_nested_many2one():
|
||||
person = Person()
|
||||
assert '<Person><ID>ole</ID></Person>' == person.to_xml()
|
||||
|
||||
def test_model_on_change_field():
|
||||
class Hash(facho.model.Model):
|
||||
__name__ = 'Hash'
|
||||
|
||||
class Person(facho.model.Model):
|
||||
__name__ = 'Person'
|
||||
|
||||
react = fields.Attribute('react')
|
||||
hash = fields.Many2One(Hash)
|
||||
|
||||
@fields.on_change(['hash'])
|
||||
def on_change_react(self, name, value):
|
||||
assert name == 'hash'
|
||||
self.react = "%s+4" % (value)
|
||||
|
||||
person = Person()
|
||||
person.hash = 'hola'
|
||||
assert '<Person react="hola+4"><Hash>hola</Hash></Person>' == person.to_xml()
|
||||
|
||||
def test_model_on_change_field_attribute():
|
||||
class Person(facho.model.Model):
|
||||
__name__ = 'Person'
|
||||
|
||||
react = fields.Attribute('react')
|
||||
hash = fields.Attribute('Hash')
|
||||
|
||||
@fields.on_change(['hash'])
|
||||
def on_change_react(self, name, value):
|
||||
assert name == 'hash'
|
||||
self.react = "%s+4" % (value)
|
||||
|
||||
person = Person()
|
||||
person.hash = 'hola'
|
||||
assert '<Person react="hola+4" Hash="hola"/>' == person.to_xml()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user