Skip to content

Instantly share code, notes, and snippets.

@jzerbe
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jzerbe/466ddec827cd766313ed to your computer and use it in GitHub Desktop.
Save jzerbe/466ddec827cd766313ed to your computer and use it in GitHub Desktop.
PolyModel for ever-more-specific selection information instead of a sparse data model
from google.appengine.ext import ndb
from google.appengine.ext.ndb import polymodel
class SelectionBinder(polymodel.PolyModel):
"""
Base class for selecting content.
https://developers.google.com/appengine/docs/python/ndb/polymodelclass
All selections are at the binder level or more specific.
"""
# the binder in which the selection resides
binder_id = ndb.StringProperty(indexed=True, required=True)
# last time the entity was put
last_modified = ndb.DateTimeProperty(auto_now=True)
# every selection is for tying some metadata to some content.
# key.urlsafe() representation of Annotation.key
# https://developers.google.com/appengine/docs/python/ndb/keyclass#Key_urlsafe
annotation_key = ndb.StringProperty(indexed=True, required=True)
class SelectionDoc(SelectionBinder):
"""
Selecting inside of a particular document.
"""
document_id = ndb.StringProperty(indexed=True, required=True)
class SelectionPage(SelectionDoc)
page_id = ndb.StringProperty(indexed=True, required=True)
class SelectionRegion(SelectionPage):
"""
A region can be a paragraph, chart, some object inside of a page.
"""
region_id = ndb.StringProperty(indexed=True, required=True)
class SelectionText(SelectionRegion):
"""
When the parent region is a paragraph, the user is selecting some text.
"""
start_index = ndb.IntegerProperty(indexed=False, required=True)
end_index = ndb.IntegerProperty(indexed=False, required=True)
class SelectionXY(SelectionRegion):
"""
Put a point over a region at an X/Y offset from the top-left.
Only works with static content.
"""
position_x = ndb.IntegerProperty(indexed=False, required=True)
position_y = ndb.IntegerProperty(indexed=False, required=True)
from google.appengine.ext import ndb
class SparseModel(ndb.Model):
def _prepare_for_put(self):
if self._properties:
# store delete work for after read is done
keys_to_remove = []
for key, value in self._properties.iteritems():
if value is None:
keys_to_remove.append(key)
# delete properties with None
for key in keys_to_remove:
del self._properties[key]
# finally dig into nested properties
for prop in self._properties.itervalues():
prop._prepare_for_put(self)
@jzerbe
Copy link
Author

jzerbe commented Aug 10, 2014

instead of dropping all None columns from existence on database put via a hack, one can be smart about instantiating entities at the appropriate specificity and reap the rewards of inheritance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment