Created
February 6, 2013 18:42
-
-
Save gregorynicholas/4724761 to your computer and use it in GitHub Desktop.
helper methods for working with appengine ndb models and dict / json serialization
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from json import JSONEncoder, loads | |
from time import mktime | |
from datetime import date, datetime | |
from google.appengine.ext import ndb | |
from google.appengine.ext.ndb import query | |
def to_epoch(value): | |
""" | |
This is a view method to return the data in milli-seconds. | |
:param value: Instance of `datetime.datetime`. | |
:returns: `float` as the number of seconds since unix epoch. | |
""" | |
return mktime(value.utctimetuple()) * 1000 | |
def from_epoch(value): | |
""" | |
:param value: | |
Instance of `float` as the number of seconds since unix epoch. | |
:returns: | |
Instance of `datetime.datetime`. | |
""" | |
return datetime.utcfromtimestamp(value / 1000) | |
def entity_to_dict(self, includes=None, excludes=None): | |
"""Encodes an `ndb.Model` to a `dict`. By default, only `ndb.Property` | |
attributes are included in the result. | |
:param include: | |
List of strings keys of class attributes. Can be the name of the | |
either a method or property. | |
:param exclude: | |
List of string keys to omit from the return value. | |
:returns: Instance of `dict`. | |
:raises: `ValueError` if any key in the `include` param doesn't exist. | |
""" | |
value = ndb.Model.to_dict(self) | |
# set the `id` of the entity's key by default.. | |
if self.key: | |
value['key'] = self.key.urlsafe() | |
value['id'] = self.key.id() | |
if includes: | |
for inc in includes: | |
attr = getattr(self, inc, None) | |
if attr is None: | |
cls = self.__class__ | |
logging.warn('entity_to_dict cannot encode `%s`. Property is \ | |
not defined on `%s.%s`.', inc, cls.__module__, cls.__name__) | |
continue | |
if callable(attr): | |
value[inc] = attr() | |
else: | |
value[inc] = attr | |
if excludes: | |
# exclude items from the result dict, by popping the keys | |
# from the dict.. | |
[value.pop(exc) for exc in excludes | |
if exc in value] | |
return value | |
def entity_from_dict(cls, value): | |
""" | |
:param cls: `ndb.Model` subclass. | |
:param value: | |
""" | |
def _decode(_result, _value): | |
""" | |
Deserializes `dict` values to `ndb.Property` values. | |
""" | |
for key, val in _value.iteritems(): | |
prop = cls._properties.get(key) | |
# logging.error('prop: %s', dir(prop)) | |
if prop is None: | |
logging.warn('entity_from_dict cannot decode: `%s`. Property is \ | |
not defined on: `%s.%s`.', key, cls.__module__, cls.__name__) | |
continue | |
if isinstance(prop, (ndb.DateTimeProperty, ndb.DateProperty, | |
ndb.TimeProperty)): | |
if prop._repeated: | |
val = [from_epoch(v) for v in val] | |
else: | |
val = from_epoch(val) | |
if isinstance(prop, ndb.BlobKeyProperty): | |
if prop._repeated: | |
val = [ndb.BlobKey(urlsafe=v) for v in val] | |
else: | |
val = ndb.BlobKey(urlsafe=val) | |
if isinstance(prop, ndb.KeyProperty): | |
if prop._repeated: | |
val = [ndb.Key(urlsafe=v) for v in val] | |
else: | |
val = ndb.Key(urlsafe=val) | |
if isinstance(prop, ndb.BlobProperty): | |
pass | |
_result[key] = val | |
return _result | |
return cls(**_decode({}, value)) | |
def entity_from_json(cls, value): | |
""" | |
Deserializes a json str to an instance of an `ndb.Model` subclass. | |
:param cls: `ndb.Model` subclass. | |
:param value: | |
""" | |
value = loads(value, strict=False) | |
if isinstance(value, list): | |
result = [entity_from_dict(cls, v) for v in value] | |
else: | |
result = entity_from_dict(cls, value) | |
return result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks bro! Worked just fine 🎯