app/soc/logic/models/base.py
changeset 565 b0c5d58f9d3e
parent 543 280a1ac6bcc1
child 592 be98a2f5d8a2
equal deleted inserted replaced
564:d928d226cfad 565:b0c5d58f9d3e
   293     if unique:
   293     if unique:
   294       return query.get()
   294       return query.get()
   295 
   295 
   296     return query.fetch(limit, offset)
   296     return query.fetch(limit, offset)
   297 
   297 
   298   def buildTypedQueryString(self):
       
   299     """Returns a GQL query string compatible with PolyModel.
       
   300     """
       
   301     return ''.join(self._buildTypedQueryParts())
       
   302 
       
   303   def _buildTypedQueryParts(self):
       
   304     if self._base_model:
       
   305       return [
       
   306           'SELECT * FROM ', self._base_model.__name__,
       
   307           " WHERE inheritance_line = '", self.getFullModelClassName(), "'"]
       
   308     
       
   309     return ['SELECT * FROM ', self._model.__name__]
       
   310 
       
   311   def buildOrderedQueryString(self, order_by=None):
       
   312     """Returns a an ordered GQL query string compatible with PolyModel.
       
   313   
       
   314     Args:
       
   315       order_by: optional field name by which to order the query results;
       
   316         default is None, in which case no ORDER BY clause is placed in
       
   317         the query string
       
   318     """
       
   319     return ''.join(self._buildOrderedQueryParts(order_by=order_by))
       
   320 
       
   321   def _buildOrderedQueryParts(self, order_by=None):
       
   322     query_str_parts = self._buildTypedQueryParts()
       
   323 
       
   324     if order_by:
       
   325       query_str_parts.extend([' ORDER BY ', order_by])
       
   326 
       
   327     return query_str_parts
       
   328 
       
   329   def getEntitiesForLimitAndOffset(self, limit, offset=0, order_by=None):
       
   330     """Returns entities for given offset and limit or None if not found.
       
   331     
       
   332     Args:
       
   333       limit: max amount of entities to return
       
   334       offset: optional offset in entities list which defines first entity to
       
   335         return; default is zero (first entity)
       
   336     """
       
   337     query_string = self.buildOrderedQueryString(order_by=order_by)
       
   338     query = db.GqlQuery(query_string)
       
   339 
       
   340     return query.fetch(limit, offset)
       
   341 
       
   342   def getNearestEntities(self, fields_to_try):
       
   343     """Get entities just before and just after the described entity.
       
   344     
       
   345     Args:
       
   346       fields_to_try: ordered list of key/value pairs that "describe"
       
   347         the desired entity (which may not necessarily exist), where key is
       
   348         the name of the field, and value is an instance of that field
       
   349         used in the comparison; if value is None, that field is skipped
       
   350 
       
   351     Returns:
       
   352       a two-tuple: ([nearest_entities], 'field_name')
       
   353     
       
   354       nearest_entities: list of entities being those just before and just
       
   355         after the (possibly non-existent) entity identified by the first
       
   356         of the supplied (non-None) fields
       
   357           OR
       
   358         possibly None if query had no results for the supplied field
       
   359         that was used.
       
   360     """
       
   361     # SELECT * FROM base_class WHERE inheritance_line = 'derived_class'
       
   362     typed_query_parts = self._buildTypedQueryParts()
       
   363   
       
   364     if self._base_model:
       
   365       typed_query_parts.append(' AND %s > :1')
       
   366     else:
       
   367       typed_query_parts.append(' WHERE %s > :1')
       
   368 
       
   369     typed_query_fmt = ''.join(typed_query_parts)
       
   370 
       
   371     for field, value in fields_to_try:
       
   372       if value is None:
       
   373         # skip this not-supplied field
       
   374         continue
       
   375 
       
   376       query = db.GqlQuery(typed_query_fmt % field, value)
       
   377       return query.fetch(1), field
       
   378 
       
   379     # all fields exhausted, and all had None values
       
   380     return (None, None)
       
   381 
       
   382   def findNearestEntitiesOffset(width, fields_to_try):
       
   383     """Finds offset of beginning of a range of entities around the nearest.
       
   384   
       
   385     Args:
       
   386       width: the width of the "found" window around the nearest User found
       
   387       fields_to_try:  see getNearestEntities()
       
   388     
       
   389     Returns:
       
   390       an offset into the list of entities that is width/2 less than the
       
   391       offset of the first entity returned by getNearestEntities(), or zero
       
   392       if that offset would be less than zero
       
   393         OR
       
   394       None if there are no nearest entities or the offset of the beginning of
       
   395       the range cannot be found for some reason 
       
   396     """
       
   397     # find entity "nearest" to supplied fields
       
   398     nearest_entities, field = self.getNearestEntities(fields_to_try)
       
   399   
       
   400     if not nearest_entities:
       
   401       # no "nearest" entity, so indicate that with None
       
   402       return None
       
   403 
       
   404     nearest_entity = nearest_entities[0]
       
   405 
       
   406     # start search for beginning of nearest Users range at offset zero
       
   407     offset = 0
       
   408     entities = self.getEntitiesForLimitAndOffset(width, offset=offset)
       
   409   
       
   410     while True:
       
   411       for entity in entities:
       
   412         if getattr(nearest_entity, field) == getattr(entity, field):
       
   413           # nearest User found in current search range, so return a range start
       
   414           return max(0, (offset - (width/2)))
       
   415 
       
   416         offset = offset + 1
       
   417 
       
   418       # nearest User was not in the current search range, so fetch the next set
       
   419       entities = self.getEntitiesForLimitAndOffset(width, offset=offset)
       
   420 
       
   421       if not entities:
       
   422         # nearest User never found, so indicate that with None
       
   423         break
       
   424 
       
   425     return None
       
   426 
       
   427   def updateModelProperties(self, model, model_properties):
   298   def updateModelProperties(self, model, model_properties):
   428     """Update existing model entity using supplied model properties.
   299     """Update existing model entity using supplied model properties.
   429 
   300 
   430     Args:
   301     Args:
   431       model: a model entity
   302       model: a model entity