bossylobster

PolyModel with endpoints-proto-datastore

Jan 10th, 2013
229
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.37 KB | None | 0 0
  1. from google.appengine.ext import ndb
  2. from google.appengine.ext.ndb import polymodel
  3. from protorpc import remote
  4.  
  5. import endpoints
  6.  
  7. from endpoints_proto_datastore.ndb import EndpointsModel
  8. from endpoints_proto_datastore.ndb.model import _EndpointsQueryInfo
  9.  
  10.  
  11. def _DowncastMessage(message, final_message_class):
  12.   message_class = message.__class__
  13.  
  14.   downcasted_message = final_message_class()
  15.   for field in final_message_class.all_fields():
  16.     # KeyError allowed to happen, if the field is missing,
  17.     # a downcast should be performed
  18.     field_on_message = message_class.field_by_name(field.name)
  19.     # Make sure fields are the same type
  20.     if field_on_message.__class__ != field.__class__:
  21.       raise TypeError('Downcasted field of the wrong type: %r. Should be %r.' %
  22.                       (field_on_message.__class__, field.__class__))
  23.     value = getattr(message, field.name)
  24.     setattr(downcasted_message, field.name, value)
  25.   return downcasted_message
  26.  
  27.  
  28. class _PolyModelQueryInfo(_EndpointsQueryInfo):
  29.  
  30.   def _PopulateFilters(self):
  31.     entity = self._entity
  32.     for prop in entity._properties.itervalues():
  33.       if isinstance(prop, polymodel._ClassKeyProperty):
  34.         continue
  35.       attr_name = prop._code_name
  36.       current_value = getattr(entity, attr_name)
  37.  
  38.       # Only filter for non-null values
  39.       if current_value is not None:
  40.         self._AddFilter(prop == current_value)
  41.  
  42.  
  43. class MyModel(EndpointsModel, polymodel.PolyModel):
  44.   _message_fields_schema = ('attr1', 'created')
  45.  
  46.   attr1 = ndb.StringProperty()
  47.   created = ndb.DateTimeProperty(auto_now_add=True)
  48.  
  49.   def __init__(self, *args, **kwargs):
  50.     # Don't need to call both constructors since PolyModel doesn't define one
  51.     # and descends from model.Model, a superclass of EndpointsModel
  52.     super(MyModel, self).__init__(*args, **kwargs)
  53.     self._endpoints_query_info = _PolyModelQueryInfo(self)
  54.  
  55.   @classmethod
  56.   def ToMessageCollection(cls, items, collection_fields=None,
  57.                           next_cursor=None):
  58.     proto_model = cls.ProtoCollection(collection_fields=collection_fields)
  59.  
  60.     items_as_message = [item.ToMessage(fields=collection_fields)
  61.                         for item in items]
  62.     final_proto_class = cls.ProtoModel(fields=collection_fields)
  63.     items_as_message = [_DowncastMessage(item, final_proto_class)
  64.                         for item in items_as_message]
  65.  
  66.     result = proto_model(items=items_as_message)
  67.  
  68.     if next_cursor is not None:
  69.       result.nextPageToken = next_cursor.to_websafe_string()
  70.  
  71.     return result
  72.  
  73.  
  74. class NextModel(MyModel):
  75.   _message_fields_schema = ('attr1', 'attr2', 'created')
  76.   attr2 = ndb.StringProperty()
  77.  
  78.  
  79. @endpoints.api(name='myapi', version='v1', description='My Little API')
  80. class MyApi(remote.Service):
  81.  
  82.   @MyModel.method(path='mymodel', http_method='POST', name='mymodel.insert')
  83.   def MyModelInsert(self, my_model):
  84.     my_model.put()
  85.     return my_model
  86.  
  87.   @MyModel.query_method(path='mymodels', name='mymodel.list')
  88.   def MyModelList(self, query):
  89.     return query
  90.  
  91.   @NextModel.method(path='nextmodel', name='nextmodel.insert')
  92.   def NextModelInsert(self, my_model):
  93.     my_model.put()
  94.     return my_model
  95.  
  96.   @NextModel.query_method(path='nextmodels', name='nextmodel.list')
  97.   def NextModelList(self, query):
  98.     return query
  99.  
  100.  
  101. application = endpoints.api_server([MyApi], restricted=False)
Advertisement
Add Comment
Please, Sign In to add comment