diff --git a/facho/model/__init__.py b/facho/model/__init__.py
index 1f6c14b..fe8cc66 100644
--- a/facho/model/__init__.py
+++ b/facho/model/__init__.py
@@ -28,7 +28,18 @@ class ModelBase(object, metaclass=ModelMeta):
def __getitem__(self, key):
return self._xml_attributes[key]
+ def __before_xml__(self):
+ pass
+
+ def _hook_before_xml(self):
+ self.__before_xml__()
+ for field in self._fields.values():
+ if hasattr(field, '__before_xml__'):
+ field.__before_xml__()
+
def to_xml(self):
+ self._hook_before_xml()
+
tag = self.__name__
ns = ''
if self._namespace_prefix is not None:
diff --git a/facho/model/fields/__init__.py b/facho/model/fields/__init__.py
index f368aaf..fb85bc9 100644
--- a/facho/model/fields/__init__.py
+++ b/facho/model/fields/__init__.py
@@ -1,5 +1,6 @@
from .attribute import Attribute
from .many2one import Many2One
from .model import Model
+from .function import Function
__all__ = [Attribute, Many2One, Model]
diff --git a/facho/model/fields/field.py b/facho/model/fields/field.py
index 251223e..e9c09ec 100644
--- a/facho/model/fields/field.py
+++ b/facho/model/fields/field.py
@@ -19,3 +19,9 @@ class Field:
if name not in namespaces:
raise KeyError("namespace %s not found" % (name))
inst._namespace_prefix = name
+
+ def _call(self, inst, method, *args):
+ call = getattr(inst, method or '', None)
+
+ if callable(call):
+ return call(*args)
diff --git a/tests/test_model.py b/tests/test_model.py
index 8aeb7e1..9d27d35 100644
--- a/tests/test_model.py
+++ b/tests/test_model.py
@@ -165,3 +165,63 @@ def test_field_model_with_namespace():
person = Person()
person.id = 33
assert '33' == person.to_xml()
+
+def test_field_hook_before_xml():
+ class Hash(facho.model.Model):
+ __name__ = 'Hash'
+
+ class Person(facho.model.Model):
+ __name__ = 'Person'
+
+ hash = fields.Model(Hash)
+
+ def __before_xml__(self):
+ self.hash = "calculate"
+
+ person = Person()
+ assert "calculate" == person.to_xml()
+
+
+def test_field_function_with_attribute():
+ class Person(facho.model.Model):
+ __name__ = 'Person'
+
+ hash = fields.Function('get_hash', field=fields.Attribute('hash'))
+
+ def get_hash(self, name, field):
+ return 'calculate'
+
+ person = Person()
+ assert ''
+
+def test_field_function():
+ class Person(facho.model.Model):
+ __name__ = 'Person'
+
+ hash = fields.Function('get_hash')
+
+ def get_hash(self, name):
+ return 'calculate'
+
+ person = Person()
+ assert person.hash == 'calculate'
+ assert "" == person.to_xml()
+
+
+def test_field_function_setter():
+ class Person(facho.model.Model):
+ __name__ = 'Person'
+
+ hash = fields.Attribute('hash')
+ password = fields.Function('get_hash', setter='set_hash')
+
+ def get_hash(self, name):
+ return None
+
+ def set_hash(self, name, value):
+ self.hash = "%s+2" % (value)
+
+ person = Person()
+ person.password = 'calculate'
+ assert '' == person.to_xml()
+