diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/logic/model.py --- a/app/soc/logic/model.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/logic/model.py Sun Oct 12 00:12:53 2008 +0000 @@ -18,13 +18,17 @@ """ __authors__ = [ + '"Todd Larsen" ', + '"Sverre Rabbelier" ', '"Pawel Solyga" ', - '"Todd Larsen" ', ] from google.appengine.ext import db +from soc.logic import key_name +from soc.logic import out_of_band + def getFullClassName(cls): """Returns fully-qualified module.class name string.""" @@ -176,34 +180,167 @@ return None -def updateModelProperties(model, **model_properties): - """Update existing model entity using supplied model properties. +class BaseLogic(): + """Base logic for entity classes. + + The BaseLogic class functions specific to Entity classes by relying + on the the child-classes to implement _model, _name and _key_name + """ + + def _updateField(self, model, name, value): + """Hook called when a field is updated. + + Base classes should override if any special actions need to be + taken when a field is updated. The field is not updated if the + method does not return a True value. + """ + + return True - Args: - model: a model entity - **model_properties: keyword arguments that correspond to model entity - properties and their values + def getFromKeyName(self, key_name): + """"Returns User entity for key_name or None if not found. +- +- Args: +- key_name: key name of entity + """ + return self._model.get_by_key_name(key_name) + + def getFromFields(self, **kwargs): + """Returns the entity for a given link name, or None if not found. + + Args: + link_name: a link name of the entity that uniquely identifies it + """ + # lookup by Sponsor key name + key_name = self.getKeyNameForFields(**kwargs) - Returns: - the original model entity with any supplied properties changed - """ - def update(): - return _unsafeUpdateModelProperties(model, **model_properties) + if key_name: + entity = self._model.get_by_key_name(key_name) + else: + entity = None + + return entity + + def getIfFields(self, **kwargs): + """Returns Sponsor entity for supplied link name if one exists. + + Args: + link_name: a link name of the Sponsor that uniquely identifies it + + Returns: + * None if link name is false. + * Sponsor entity for supplied link_name - return db.run_in_transaction(update) + Raises: + out_of_band.ErrorResponse if link name is not false, but no Sponsor entity + with the supplied link name exists in the Datastore + """ + if not all(kwargs.values()): + # exit without error, to let view know that link_name was not supplied + return None + + entity = self.getFromFields(**kwargs) + + if entity: + # a Sponsor exist for this link_name, so return that Sponsor entity + return entity + + fields = [] + + for key, value in kwargs.iteritems(): + fields.extend('"%s" is "%s"' % (key, value)) + + # else: fields were supplied, but there is no Entity that has it + raise out_of_band.ErrorResponse( + 'There is no %s with %s.' % (self._name, ''.join(fields)), status=404) + + def getKeyNameForFields(self, **kwargs): + """Return a Datastore key_name for a Sponsor from the link name. + Args: + link_name: a link name of the entity that uniquely identifies it + """ + if not all(kwargs.values()): + return None -def _unsafeUpdateModelProperties(model, **model_properties): - """(see updateModelProperties) + return self._keyName(**kwargs) + + def getForLimitAndOffset(self, limit, offset=0): + """Returns entities for given offset and limit or None if not found. + + Args: + limit: max amount of entities to return + offset: optional offset in entities list which defines first entity to + return; default is zero (first entity) + """ + query = self._model.all() + return query.fetch(limit, offset) - Like updateModelProperties(), but not run within a transaction. - """ - properties = model.properties() + def updateModelProperties(self, model, **model_properties): + """Update existing model entity using supplied model properties. + + Args: + model: a model entity + **model_properties: keyword arguments that correspond to model entity + properties and their values + + Returns: + the original model entity with any supplied properties changed + """ + def update(): + return self._unsafeUpdateModelProperties(model, **model_properties) + + return db.run_in_transaction(update) + + def _unsafeUpdateModelProperties(self, model, **model_properties): + """(see updateModelProperties) + + Like updateModelProperties(), but not run within a transaction. + """ + properties = model.properties() - for prop in properties.values(): - if prop.name in model_properties: - value = model_properties[prop.name] - prop.__set__(model, value) + for prop in properties.values(): + name = prop.name + + if not name in self._skip_properties and name in model_properties: + value = model_properties[prop.name] + + if self._updateField(model, name, value): + prop.__set__(model, value) + + model.put() + return model + + def updateOrCreateFromKeyName(self, properties, key_name): + """Update existing entity, or create new one with supplied properties. + + Args: + link_name: a link_name of the entity that uniquely identifies it + **properties: keyword arguments that correspond to entity + properties and their values - model.put() - return model \ No newline at end of file + Returns: + the entity corresponding to the key_name, with any supplied + properties changed, or a new entity now associated with the + supplied key_name and properties. + """ + + entity = self.getFromKeyName(key_name) + + if not entity: + # entity did not exist, so create one in a transaction + entity = self._model.get_or_insert(key_name, **properties) + + # there is no way to be sure if get_or_insert() returned a new entity or + # got an existing one due to a race, so update with sponsor_properties anyway, + # in a transaction + return self.updateModelProperties(entity, **properties) + + def updateOrCreateFromFields(self, properties, **kwargs): + """Like updateOrCreateFromKeyName, but resolves **kwargs to a key_name first + """ + + # attempt to retrieve the existing entity + key_name = self.getKeyNameForFields(**kwargs) + + return self.updateOrCreateFromKeyName(properties, key_name)