From b23f69b7c727421fd2dab2ff5ccba52fcb26fc7a Mon Sep 17 00:00:00 2001 From: Jeff Jenkins Date: Thu, 7 Apr 2011 18:55:21 -0400 Subject: [PATCH] Issue 53 -- Separate DB-initated object field setting from user intiated --- examples/advanced_modeling.py | 36 +++++++++++++++++++++-------------- examples/hash_field.py | 30 +++++++++++++++++++++++++++++ mongoalchemy/document.py | 6 +++--- mongoalchemy/fields.py | 9 ++++++--- 4 files changed, 61 insertions(+), 20 deletions(-) create mode 100644 examples/hash_field.py diff --git a/examples/advanced_modeling.py b/examples/advanced_modeling.py index b462b44..f75e78e 100644 --- a/examples/advanced_modeling.py +++ b/examples/advanced_modeling.py @@ -1,32 +1,40 @@ +''' +This page is going to go through some more advanced modeling techniques +using forward and self-references + +''' + + from mongoalchemy.document import Document, DocumentField from mongoalchemy.fields import * from datetime import datetime - +from pprint import pprint class Event(Document): name = StringField() - children = ListField(DocumentField('Event'), default=[]) - start = DateTimeField() + children = ListField(DocumentField('Event')) + begin = DateTimeField() end = DateTimeField() def __init__(self, name, parent=None): Document.__init__(self, name=name) + self.children = [] if parent != None: parent.children.append(self) def __enter__(self): - self.start = datetime.utcnow() + self.begin = datetime.utcnow() return self def __exit__(self, exc_type, exc_val, exc_tb): self.end = datetime.utcnow() -root = Event('request') -with Event('main_func', root) as br: - with Event('setup', br): - pass - with Event('handle', br): - pass - with Event('teardown', br): +with Event('request') as root: + with Event('main_func', root) as br: + with Event('setup', br): + pass + with Event('handle', br): + pass + with Event('teardown', br): + pass + with Event('cleanup', root): pass -with Event('cleanup', root): - pass -print root.wrap() +pprint(root.wrap()) diff --git a/examples/hash_field.py b/examples/hash_field.py new file mode 100644 index 0000000..bc11c34 --- /dev/null +++ b/examples/hash_field.py @@ -0,0 +1,30 @@ +from mongoalchemy.document import Document, DocumentField +from mongoalchemy.fields import * +from datetime import datetime +from pprint import pprint + +class HashField(StringField): + def set_value(self, instance, value, from_db=False): + if from_db: + super(HashField, self).set_value(instance, value) + else: + super(HashField, self).set_value(instance, str(hash(value))) + +class User(Document): + password = HashField() + +from mongoalchemy.session import Session +session = Session.connect('mongoalchemy-tutorial') +session.clear_collection(User) + +user = User(password='pw') +print user.password +user.password = 'newpw' +print user.password + +session.insert(user) + +loaded_user = session.query(User).one() + +print loaded_user.password +print loaded_user.password \ No newline at end of file diff --git a/mongoalchemy/document.py b/mongoalchemy/document.py index 524c127..6946c2a 100644 --- a/mongoalchemy/document.py +++ b/mongoalchemy/document.py @@ -116,7 +116,7 @@ class Document(object): fields which couldn't be mapped can be retrieved (and edited) using :func:`~Document.get_extra_fields` ''' - def __init__(self, retrieved_fields=None, **kwargs): + def __init__(self, retrieved_fields=None, loading_from_db=False, **kwargs): ''' :param retrieved_fields: The names of the fields returned when loading \ a partial object. This argument should not be explicitly set \ by subclasses @@ -141,7 +141,7 @@ def __init__(self, retrieved_fields=None, **kwargs): continue if name in kwargs: - setattr(self, name, kwargs[name]) + getattr(cls, name).set_value(self, kwargs[name], from_db=loading_from_db) continue for k in kwargs: @@ -315,7 +315,7 @@ def unwrap(cls, obj, fields=None): if fields != None: params['retrieved_fields'] = fields - obj = cls(**params) + obj = cls(loading_from_db=True, **params) obj.__mark_clean() return obj diff --git a/mongoalchemy/fields.py b/mongoalchemy/fields.py index 28dc3c9..e2db1ae 100644 --- a/mongoalchemy/fields.py +++ b/mongoalchemy/fields.py @@ -183,9 +183,7 @@ def __get__(self, instance, owner): def __set__(self, instance, value): - instance._field_values[self.name] = value - if self.on_update != 'ignore': - instance._dirty[self.name] = self.on_update + self.set_value(instance, value) def __delete__(self, instance): if self.name not in instance._field_values: @@ -193,6 +191,11 @@ def __delete__(self, instance): del instance._field_values[self.name] instance._dirty[self.name] = '$unset' + def set_value(self, instance, value, from_db=False): + instance._field_values[self.name] = value + if self.on_update != 'ignore': + instance._dirty[self.name] = self.on_update + def dirty_ops(self, instance): op = instance._dirty.get(self.name) if op == '$unset':