app/soc/logic/models/base.py
changeset 435 829fe8302a8b
parent 433 001b981be45e
child 436 f3c313d54aa4
equal deleted inserted replaced
434:a4fc430fefac 435:829fe8302a8b
    27 
    27 
    28 from google.appengine.ext import db
    28 from google.appengine.ext import db
    29 
    29 
    30 from django.utils.translation import ugettext_lazy
    30 from django.utils.translation import ugettext_lazy
    31 
    31 
       
    32 from soc.logic import dicts
    32 from soc.logic import out_of_band
    33 from soc.logic import out_of_band
    33 
    34 
    34 
    35 
    35 class Logic:
    36 class Logic:
    36   """Base logic for entity classes.
    37   """Base logic for entity classes.
   116 
   117 
   117     key_values = self.getKeyValues(entity)
   118     key_values = self.getKeyValues(entity)
   118     suffix = '/'.join(key_values)
   119     suffix = '/'.join(key_values)
   119 
   120 
   120     return suffix
   121     return suffix
       
   122 
       
   123   def getKeyFieldsFromDict(self, dictionary):
       
   124     """Does any required massaging and filtering of dictionary
       
   125 
       
   126     The resulting dictionary contains just the key names, and has any
       
   127     required translations/modifications performed.
       
   128 
       
   129     Args:
       
   130       dictionary: The arguments to massage
       
   131     """
       
   132 
       
   133     keys = self.getKeyFieldNames()
       
   134     values = self.getKeyValuesFromFields(dictionary)
       
   135     key_fields = dicts.zip(keys, values)
       
   136 
       
   137     return key_fields
   121 
   138 
   122   def getFromKeyName(self, key_name):
   139   def getFromKeyName(self, key_name):
   123     """"Returns User entity for key_name or None if not found.
   140     """"Returns User entity for key_name or None if not found.
   124 -
   141 -
   125 -    Args:
   142 -    Args:
   127     """
   144     """
   128 
   145 
   129     return self._model.get_by_key_name(key_name)
   146     return self._model.get_by_key_name(key_name)
   130 
   147 
   131   def getFromFields(self, **kwargs):
   148   def getFromFields(self, **kwargs):
   132     """Returns the entity for a given link name, or None if not found.
   149     """Returns the entity for the specified key names, or None if not found.
   133 
   150 
   134     Args:
   151     Args:
   135       **kwargs: the fields of the entity that uniquely identifies it
   152       **kwargs: the fields of the entity that uniquely identifies it
   136     """
   153     """
   137 
   154 
   138     key_name = self.getKeyNameForFields(**kwargs)
   155     key_name = self.getKeyNameForFields(kwargs)
   139 
   156 
   140     if key_name:
   157     if key_name:
   141       entity = self._model.get_by_key_name(key_name)
   158       entity = self._model.get_by_key_name(key_name)
   142     else:
   159     else:
   143       entity = None
   160       entity = None
   144 
   161 
   145     return entity
   162     return entity
   146 
   163 
   147   def getIfFields(self, **kwargs):
   164   def getIfFields(self, fields):
   148     """Returns entity for supplied link name if one exists.
   165     """Returns entity for supplied link name if one exists.
   149 
   166 
   150     Args:
   167     Args:
   151       **kwargs: the fields of the entity that uniquely identifies it
   168       fields: the fields of the entity that uniquely identifies it
   152 
   169 
   153     Returns:
   170     Returns:
   154       * None if a field is false.
   171       * None if a field is false.
   155       * Entity for supplied fields
   172       * Entity for supplied fields
   156 
   173 
   157     Raises:
   174     Raises:
   158       out_of_band.ErrorResponse if link name is not false, but no entity
   175       out_of_band.ErrorResponse if link name is not false, but no entity
   159       with the supplied link name exists in the Datastore
   176       with the supplied link name exists in the Datastore
   160     """
   177     """
   161 
   178 
   162     if not all(kwargs.values()):
   179     if not all(fields.values()):
   163       # exit without error, to let view know that link_name was not supplied
   180       # exit without error, to let view know that link_name was not supplied
   164       return None
   181       return None
   165 
   182 
   166     entity = self.getFromFields(**kwargs)
   183     entity = self.getFromFields(**fields)
   167 
   184 
   168     if entity:
   185     if entity:
   169       # an entity exist for this link_name, so return that entity
   186       # an entity exist for this link_name, so return that entity
   170       return entity
   187       return entity
   171 
   188 
   172     fields = []
   189     fields = []
   173 
   190 
   174     format_text = ugettext_lazy('"%(key)s" is "%(value)s"')
   191     format_text = ugettext_lazy('"%(key)s" is "%(value)s"')
   175 
   192 
   176     msg_pairs = [format_text % {'key': key, 'value': value}
   193     msg_pairs = [format_text % {'key': key, 'value': value}
   177       for key, value in kwargs.iteritems()]
   194       for key, value in fields.iteritems()]
   178 
   195 
   179     joined_pairs = ' and '.join(msg_pairs)
   196     joined_pairs = ' and '.join(msg_pairs)
   180 
   197 
   181     msg = ugettext_lazy(
   198     msg = ugettext_lazy(
   182       'There is no "%(name)s" where %(pairs)s.') % {
   199       'There is no "%(name)s" where %(pairs)s.') % {
   184 
   201 
   185 
   202 
   186     # else: fields were supplied, but there is no Entity that has it
   203     # else: fields were supplied, but there is no Entity that has it
   187     raise out_of_band.ErrorResponse(msg, status=404)
   204     raise out_of_band.ErrorResponse(msg, status=404)
   188 
   205 
   189   def getKeyNameForFields(self, **kwargs):
   206   def getKeyNameForFields(self, fields):
   190     """Return a Datastore key_name for a Entity from the specified fields.
   207     """Return a Datastore key_name for a Entity from the specified fields.
   191 
   208 
   192     Args:
   209     Args:
   193       **kwargs: the fields of the entity that uniquely identifies it
   210       fields: the fields of the entity that uniquely identifies it
   194     """
   211     """
   195 
   212 
   196     if not all(kwargs.values()):
   213     if not all(fields.values()):
   197       return None
   214       return None
   198 
   215 
   199     return self._keyName(**kwargs)
   216     return self._keyName(**fields)
   200 
   217 
   201   def getForLimitAndOffset(self, limit, offset=0):
   218   def getForLimitAndOffset(self, limit, offset=0):
   202     """Returns entities for given offset and limit or None if not found.
   219     """Returns entities for given offset and limit or None if not found.
   203 
   220 
   204     Args:
   221     Args:
   205       limit: max amount of entities to return
   222       limit: max amount of entities to return
   206       offset: optional offset in entities list which defines first entity to
   223       offset: optional number of results to skip first; default zero.
   207         return; default is zero (first entity)
       
   208     """
   224     """
   209 
   225 
   210     query = self._model.all()
   226     query = self._model.all()
   211     return query.fetch(limit, offset)
   227     return query.fetch(limit, offset)
   212 
   228 
   234       return query.get()
   250       return query.get()
   235 
   251 
   236     result = query.fetch(limit, offset)
   252     result = query.fetch(limit, offset)
   237     return result
   253     return result
   238 
   254 
   239   def updateModelProperties(self, model, **model_properties):
   255   def updateModelProperties(self, model, model_properties):
   240     """Update existing model entity using supplied model properties.
   256     """Update existing model entity using supplied model properties.
   241 
   257 
   242     Args:
   258     Args:
   243       model: a model entity
   259       model: a model entity
   244       **model_properties: keyword arguments that correspond to model entity
   260       model_properties: keyword arguments that correspond to model entity
   245         properties and their values
   261         properties and their values
   246 
   262 
   247     Returns:
   263     Returns:
   248       the original model entity with any supplied properties changed
   264       the original model entity with any supplied properties changed
   249     """
   265     """
   250 
   266 
   251     def update():
   267     def update():
   252       return self._unsafeUpdateModelProperties(model, **model_properties)
   268       return self._unsafeUpdateModelProperties(model, model_properties)
   253 
   269 
   254     return db.run_in_transaction(update)
   270     return db.run_in_transaction(update)
   255 
   271 
   256   def _unsafeUpdateModelProperties(self, model, **model_properties):
   272   def _unsafeUpdateModelProperties(self, model, model_properties):
   257     """(see updateModelProperties)
   273     """(see updateModelProperties)
   258 
   274 
   259     Like updateModelProperties(), but not run within a transaction.
   275     Like updateModelProperties(), but not run within a transaction.
   260     """
   276     """
   261 
   277 
   293       entity = self._model.get_or_insert(key_name, **properties)
   309       entity = self._model.get_or_insert(key_name, **properties)
   294 
   310 
   295     # there is no way to be sure if get_or_insert() returned a new entity or
   311     # there is no way to be sure if get_or_insert() returned a new entity or
   296     # got an existing one due to a race, so update with properties anyway,
   312     # got an existing one due to a race, so update with properties anyway,
   297     # in a transaction
   313     # in a transaction
   298     return self.updateModelProperties(entity, **properties)
   314     return self.updateModelProperties(entity, properties)
   299 
   315 
   300   def updateOrCreateFromFields(self, properties, **kwargs):
   316   def updateOrCreateFromFields(self, properties, fields):
   301     """Like updateOrCreateFromKeyName, but resolves **kwargs to a key_name first.
   317     """Like updateOrCreateFromKeyName, but resolves fields to a key_name first.
   302     """
   318     """
   303 
   319 
   304     # attempt to retrieve the existing entity
   320     # attempt to retrieve the existing entity
   305     key_name  = self.getKeyNameForFields(**kwargs)
   321     key_name  = self.getKeyNameForFields(fields)
   306 
   322 
   307     return self.updateOrCreateFromKeyName(properties, key_name)
   323     return self.updateOrCreateFromKeyName(properties, key_name)
   308 
   324 
   309   def isDeletable(self, entity):
   325   def isDeletable(self, entity):
   310     """Returns whether the specified entity can be deleted.
   326     """Returns whether the specified entity can be deleted.