# HG changeset patch # User Sverre Rabbelier # Date 1223770373 0 # Node ID a1cc853a56e5d6dbfd4e174ecfa3b86661bb5f6a # Parent c76a366c7ab45b19f245f70350535bfe3b376a61 Refactor nearly all the soc.logic code to use the Base class Instead of having a lot of duplicate code, this patch aims to reduce this duplication by introducing a Base abstraction. Patch by: Sverre Rabbelier Reviewed by: to-be-reviewed diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/logic/__init__.py --- a/app/soc/logic/__init__.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/logic/__init__.py Sun Oct 12 00:12:53 2008 +0000 @@ -0,0 +1,119 @@ +#!/usr/bin/python2.5 +# +# Copyright 2008 the Melange authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Various (Model) query functions. +""" + +__authors__ = [ + '"Sverre Rabbelier" ', + ] + + +import key_name +import model +import soc.models.document +import soc.models.sponsor +import soc.models.work +import soc.models.site_settings + + +class DocumentLogic(model.BaseLogic): + """Logic methods for the Document model + """ + + def __init__(self): + """Defines the name, key_name and model for this entity. + """ + + self._name = "document" + self._model = soc.models.document.Document + self._keyName = key_name.nameDocument + self._skip_properties = [] + + +class SettingsLogic(model.BaseLogic): + """Logic methods for the Settings model + """ + + + def __init__(self): + """Defines the name, key_name and model for this entity. + """ + + self._name = "settings" + self._model = soc.models.site_settings.SiteSettings + self._keyName = key_name.nameSiteSettings + self._skip_properties = [] + + +class SponsorLogic(model.BaseLogic): + """Logic methods for the Sponsor model + """ + + def __init__(self): + """Defines the name, key_name and model for this entity. + """ + + self._name = "sponsor" + self._model = soc.models.sponsor.Sponsor + self._keyName = key_name.nameSponsor + self._skip_properties = [] + + +class UserLogic(model.BaseLogic): + """Logic methods for the User model + """ + + def __init__(self): + """Defines the name, key_name and model for this entity. + """ + + self._name = "user" + self._model = soc.models.user.User + self._keyName = key_name.nameUser + self._skip_properties = ['former_ids'] + + def _updateField(self, model, name, value): + """Special case logic for id. + + When the id is changed, the former_ids field should be appended + with the old id. + """ + if name == 'id' and model.id != value: + model.former_ids.append(model.id) + + return True + +class WorkLogic(model.BaseLogic): + """Logic methods for the Work model + """ + + def __init__(self): + """Defines the name, key_name and model for this entity. + """ + + self._name = "work" + self._model = soc.models.work.Work + self._keyName = key_name.nameWork + self._skip_properties = [] + # TODO(tlarsen) write a nameWork method + + +document_logic = DocumentLogic() +settings_logic = SettingsLogic() +sponsor_logic = SponsorLogic() +user_logic = UserLogic() +work_logic = WorkLogic() diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/logic/document.py --- a/app/soc/logic/document.py Sun Oct 12 00:08:54 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -#!/usr/bin/python2.5 -# -# Copyright 2008 the Melange authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Document (Model) query functions. -""" - -__authors__ = [ - '"Pawel Solyga" ', - '"Todd Larsen" ', - ] - - -import re - -from google.appengine.ext import db - -from soc.logic import key_name -from soc.logic import out_of_band -from soc.logic.site import id_user - -from soc.logic import model - -import soc.models.document - - -def getDocument(path, link_name=None): - """Returns Document entity for a given path, or None if not found. - - Args: - path: a request path of the Document that uniquely identifies it - link_name: optional link name to append to path (when supplied, - path is actually a "partial path" that needs to link name appended - to it) - """ - # lookup by Doc:path key name - name = key_name.nameDocument(path, link_name=link_name) - - if name: - document = soc.models.document.Document.get_by_key_name(name) - else: - document = None - - return document - - -def getDocumentIfPath(path, link_name=None): - """Returns Document entity for supplied path if one exists. - - Args: - path: path used in URLs to identify document - - Returns: - * None if path is false. - * Document entity that has supplied path - - Raises: - out_of_band.ErrorResponse if path is not false, but no Document entity - with the supplied path exists in the Datastore - """ - if not path: - # exit without error, to let view know that link_name was not supplied - return None - - path_doc = getDocument(path, link_name=link_name) - - if path_doc: - # a Document has this path, so return that corresponding Document entity - return path_doc - - # else: a path was supplied, but there is no Document that has it - raise out_of_band.ErrorResponse( - 'There is no document with a "path" of "%s".' % path, status=404) - - -def updateOrCreateDocument(**document_properties): - """Update existing Document entity, or create new one with supplied properties. - - Args: - path: a request path of the Document that uniquely identifies it - **document_properties: keyword arguments that correspond to Document entity - properties and their values - - Returns: - the Document entity corresponding to the path, with any supplied - properties changed, or a new Document entity now associated with the - supplied path and properties. - """ - # attempt to retrieve the existing Document - document = getDocument(document_properties['partial_path'], - link_name=document_properties['link_name']) - - if not document: - # document did not exist, so create one in a transaction - name = key_name.nameDocument(document_properties['partial_path'], - document_properties['link_name']) - document = soc.models.document.Document.get_or_insert( - name, **document_properties) - - # there is no way to be sure if get_or_insert() returned a new Document or - # got an existing one due to a race, so update with document_properties anyway, - # in a transaction - return soc.logic.model.updateModelProperties(document, **document_properties) diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/logic/helper/access.py --- a/app/soc/logic/helper/access.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/logic/helper/access.py Sun Oct 12 00:12:53 2008 +0000 @@ -97,7 +97,7 @@ checkIsLoggedIn(request) id = users.get_current_user() - user = id_user.getUserFromId(id) + user = soc.logic.user_logic.getFromFields(email=id) if user: return diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/logic/key_name.py --- a/app/soc/logic/key_name.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/logic/key_name.py Sun Oct 12 00:12:53 2008 +0000 @@ -144,3 +144,13 @@ raise Error('"link_name" must be non-False: "%s"' % link_name) return 'Group/Club:%s' % link_name + + +def nameWork(link_name): + """Placeholder for work namer""" + + if not link_name: + raise Error('"link_name" must be non-False: "%s"' % link_name) + + return 'Work:%s' % link_name + 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) diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/logic/site/id_user.py --- a/app/soc/logic/site/id_user.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/logic/site/id_user.py Sun Oct 12 00:12:53 2008 +0000 @@ -28,6 +28,7 @@ from google.appengine.api import users from google.appengine.ext import db +import soc.logic from soc.logic import key_name from soc.logic import model from soc.logic import out_of_band @@ -35,107 +36,6 @@ import soc.models.user -def getUserKeyNameFromId(id): - """Return a Datastore key_name for a User derived from a Google Account. - - Args: - id: a Google Account (users.User) object - """ - if not id: - return None - - return key_name.nameUser(id.email()) - - -def getIdIfMissing(id=None): - """Gets Google Account of logged-in user (possibly None) if id is false. - - This is a convenience function that simplifies a lot of view code that - accepts an optional id argument from the caller (such as one looked up - already by another view that decides to "forward" the request to this - other view). - - Args: - id: a Google Account (users.User) object, or None - - Returns: - If id is non-false, it is simply returned; otherwise, the Google Account - of currently logged-in user is returned (which could be None if no user - is logged in). - """ - if not id: - # id not initialized, so check if a Google Account is currently logged in - id = users.get_current_user() - - return id - - -def getUsersForLimitAndOffset(limit, offset=0): - """Returns Users 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) - """ - return model.getEntitiesForLimitAndOffset( - soc.models.user.User, limit, offset=offset, order_by='id') - - -def getUserFromId(id): - """Returns User entity for a Google Account, or None if not found. - - Args: - id: a Google Account (users.User) object - """ - return soc.models.user.User.gql('WHERE id = :1', id).get() - - -def getUserIfMissing(user, id): - """Conditionally returns User entity for a Google Account. - - This function is used to look up the User entity corresponding to the - supplied Google Account *if* the user parameter is false (usually None). - This function is basically a no-op if user already refers to a User - entity. This is a convenience function that simplifies a lot of view - code that accepts an optional user argument from the caller (such as - one looked up already by another view that decides to "forward" the - HTTP request to this other view). - - Args: - user: None (usually), or an existing User entity - id: a Google Account (users.User) object - - Returns: - * user (which may have already been None if passed in that way by the - caller) if id is false or user is non-false - * results of getUserFromId() if user is false and id is non-false - """ - if id and (not user): - # Google Account supplied and User uninitialized, so look up User entity - user = getUserFromId(id) - - return user - - -def getNearestUsers(id=None, link_name=None): - """Get User entities just before and just after the specified User. - - Args: - id: a Google Account (users.User) object; default is None (not supplied) - link_name: link name string; default is None (not supplied) - - Returns: - User entities being those just before and just after the (possibly - non-existent) User for given id or link_name, - OR - possibly None if query had no results or neither id or link_name were - supplied. - """ - return model.getNearestEntities( - soc.models.user.User, [('id', id), ('link_name', link_name)]) - - def findNearestUsersOffset(width, id=None, link_name=None): """Finds offset of beginning of a range of Users around the nearest User. @@ -156,40 +56,6 @@ width, soc.models.user.User, [('id', id), ('link_name', link_name)]) -def doesUserExist(id): - """Returns True if User exists in the Datastore for a Google Account. - - Args: - id: a Google Account object - """ - if getUserFromId(id): - return True - else: - return False - - -def isIdUser(id=None): - """Returns True if a Google Account has it's User entity in datastore. - - Args: - id: a Google Account (users.User) object; if id is not supplied, - the current logged-in user is checked - """ - id = getIdIfMissing(id) - - if not id: - # no Google Account was supplied or is logged in - return False - - user = getUserFromId(id) - - if not user: - # no User entity for this Google Account - return False - - return True - - def isIdDeveloper(id=None): """Returns True if a Google Account is a Developer with special privileges. @@ -206,20 +72,25 @@ id: a Google Account (users.User) object; if id is not supplied, the current logged-in user is checked """ - id = getIdIfMissing(id) - - if not id: + + # Get the currently logged in user + current_id = users.get_current_user() + + if not (id or current_id): # no Google Account was supplied or is logged in, so an unspecified # User is definitely *not* a Developer return False - if id == users.get_current_user(): - if users.is_current_user_admin(): - # supplied id is current logged-in user, and that user is in the - # Administration->Developers list in the App Engine console - return True - - user = getUserFromId(id) + if (not id or id == current_id) and users.is_current_user_admin(): + # no id supplied, or current logged-in user, and that user is in the + # Administration->Developers list in the App Engine console + return True + + # If no id is specified, default to logged in user + if not id: + id = current_id + + user = soc.logic.user_logic.getFromFields(id=id) if not user: # no User entity for this Google Account, and id is not the currently @@ -241,7 +112,7 @@ when existing_user is not supplied; default is None """ if not existing_user: - existing_user = getUserFromKeyName(existing_key_name) + existing_user = soc.logic.user_logic.getFromKeyName(existing_key_name) if existing_user: old_email = existing_user.id.email() @@ -253,7 +124,7 @@ return True # else: "new" email truly is new to the existing User, so keep checking - if not isIdUser(new_id): + if not soc.logic.user_logic.getFromFields(id=new_id): # new email address also does not belong to any other User, # so it is available return True @@ -271,201 +142,38 @@ return soc.models.user.User.gql('WHERE link_name = :1', link_name).get() -def getUserFromKeyName(key_name): - """Returns User entity for key_name or None if not found. - - Args: - key_name: key name of User entity - """ - return soc.models.user.User.get_by_key_name(key_name) - - -def getUserIfLinkName(link_name): - """Returns User entity for supplied link_name if one exists. - - Args: - link_name: link name used in URLs to identify user - - Returns: - * None if link_name is false. - * User entity that has supplied link_name +def getUserFromLinkNameOrDie(link_name): + """Like getUserFromLinkName but expects to find a user Raises: - out_of_band.ErrorResponse if link_name is not false, but no User entity - with the supplied link_name exists in the Datastore + out_of_band.ErrorResponse if no User entity is found """ - if not link_name: - # exit without error, to let view know that link_name was not supplied - return None - link_name_user = getUserFromLinkName(link_name) - - if link_name_user: - # a User has this link name, so return that corresponding User entity - return link_name_user + user = getUserFromLinkName(link_name) - # else: a link name was supplied, but there is no User that has it + if user: + return user + raise out_of_band.ErrorResponse( 'There is no user with a "link name" of "%s".' % link_name, status=404) -def isLinkNameAvailableForId(link_name, id=None): - """Indicates if link name is available for the given Google Account. - - Args: - link_name: link name used in URLs to identify user - id: a Google Account object; optional, current logged-in user will - be used (or False will be returned if no user is logged in) - - Returns: - True: the link name does not exist in the Datastore, - so it is currently "available" to any User - True: the link name exists and already belongs to the User entity - associated with the specified Google Account - False: the link name exists and belongs to a User entity other than - that associated with the supplied Google Account - """ - link_name_exists = doesLinkNameExist(link_name) - - if not link_name_exists: - # if the link name does not exist, it is clearly available for any User - return True - - return doesLinkNameBelongToId(link_name, id=id) - - -def doesLinkNameExist(link_name=None): - """Returns True if link name exists in the Datastore. - - Args: - link_name: link name used in URLs to identify user - """ - if getUserFromLinkName(link_name): - return True - else: - return False - - -def doesLinkNameBelongToId(link_name, id=None): +def doesLinkNameBelongToId(link_name, id): """Returns True if supplied link name belongs to supplied Google Account. Args: link_name: link name used in URLs to identify user - id: a Google Account object; optional, current logged-in user will - be used (or False will be returned if no user is logged in) + id: a Google Account object """ - id = getIdIfMissing(id) - + if not id: - # id not supplied and no Google Account logged in, so link name cannot - # belong to an unspecified User + # link name cannot belong to an unspecified User return False - user = getUserFromId(id) + user = soc.logic.user_logic.getFromFields(email=id.email()) if not user: # no User corresponding to id Google Account, so no link name at all return False - if user.link_name != link_name: - # User exists for id, but does not have this link name - return False - - return True # link_name does actually belong to this Google Account - - -def updateOrCreateUserFromId(id, **user_properties): - """Update existing User entity, or create new one with supplied properties. - - Args: - id: a Google Account object - **user_properties: keyword arguments that correspond to User entity - properties and their values - - Returns: - the User entity corresponding to the Google Account, with any supplied - properties changed, or a new User entity now associated with the Google - Account and with the supplied properties - """ - # attempt to retrieve the existing User - user = getUserFromId(id) - - if not user: - # user did not exist, so create one in a transaction - key_name = getUserKeyNameFromId(id) - user = soc.models.user.User.get_or_insert( - key_name, id=id, **user_properties) - - # there is no way to be sure if get_or_insert() returned a new User or - # got an existing one due to a race, so update with user_properties anyway, - # in a transaction - return updateUserProperties(user, **user_properties) - - -def updateUserForKeyName(key_name, **user_properties): - """Update existing User entity for keyname with supplied properties. - - Args: - key_name: key name of User entity - **user_properties: keyword arguments that correspond to User entity - properties and their values - - Returns: - the User entity corresponding to the Google Account, with any supplied - properties changed, or a new User entity now associated with the Google - Account and with the supplied properties - """ - # attempt to retrieve the existing User - user = getUserFromKeyName(key_name) - - if not user: - return None - - # there is no way to be sure if get_or_insert() returned a new User or - # got an existing one due to a race, so update with user_properties anyway, - # in a transaction - return updateUserProperties(user, **user_properties) - - -def updateUserProperties(user, **user_properties): - """Update existing User entity using supplied User properties. - - Args: - user: a User entity - **user_properties: keyword arguments that correspond to User entity - properties and their values - - Returns: - the original User entity with any supplied properties changed - """ - def update(): - return _unsafeUpdateUserProperties(user, **user_properties) - - return db.run_in_transaction(update) - - -def _unsafeUpdateUserProperties(user, **user_properties): - """(see updateUserProperties) - - Like updateUserProperties(), but not run within a transaction. - """ - properties = user.properties() - - for prop in properties.values(): - if prop.name in user_properties: - if prop.name == 'former_ids': - # former_ids cannot be overwritten directly - continue - - value = user_properties[prop.name] - - if prop.name == 'id': - old_id = user.id - - if value != old_id: - user.former_ids.append(old_id) - - prop.__set__(user, value) - - user.put() - return user + return user.link_name == link_name diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/logic/site/map.py --- a/app/soc/logic/site/map.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/logic/site/map.py Sun Oct 12 00:12:53 2008 +0000 @@ -30,7 +30,9 @@ from django.conf.urls import defaults from django.utils import datastructures -from soc.logic import path_link_name +import soc.logic +import soc.logic.path_link_name + from soc.logic.site import page @@ -82,7 +84,7 @@ user_edit = page.Page( page.Url( - r'^user/profile/%s$' % path_link_name.LINKNAME_ARG_PATTERN, + r'^user/profile/%s$' % soc.logic.path_link_name.LINKNAME_ARG_PATTERN, 'soc.views.user.profile.edit'), 'User: Modify Existing User Profile', parent=user_signout) @@ -123,7 +125,7 @@ site_user_edit = page.Page( page.Url( - r'^site/user/profile/%s$' % path_link_name.LINKNAME_ARG_PATTERN, + r'^site/user/profile/%s$' % soc.logic.path_link_name.LINKNAME_ARG_PATTERN, 'soc.views.site.user.profile.edit'), 'Site: Modify Existing User Profile', short_name='Modify Site User', @@ -140,7 +142,7 @@ # Document views docs_show = page.Page( page.Url( - r'^docs/show/%s$' % path_link_name.PATH_LINKNAME_ARGS_PATTERN, + r'^docs/show/%s$' % soc.logic.path_link_name.PATH_LINKNAME_ARGS_PATTERN, 'soc.views.docs.show.public'), 'Show Document', parent=home) @@ -156,7 +158,7 @@ site_docs_edit = page.Page( page.Url( - r'^site/docs/edit/%s$' % path_link_name.PATH_LINKNAME_ARGS_PATTERN, + r'^site/docs/edit/%s$' % soc.logic.path_link_name.PATH_LINKNAME_ARGS_PATTERN, 'soc.views.site.docs.edit.edit'), 'Site: Modify Existing Document', short_name='Modify Site Document', @@ -173,7 +175,7 @@ # Sponsor Group public view sponsor_profile = page.Page( page.Url( - r'^sponsor/profile/%s' % path_link_name.LINKNAME_ARG_PATTERN, + r'^sponsor/profile/%s' % soc.logic.path_link_name.LINKNAME_ARG_PATTERN, 'soc.views.sponsor.profile.public'), 'Public Profile', parent=home) @@ -189,7 +191,7 @@ site_sponsor_delete = page.Page( page.Url( - r'^site/sponsor/profile/%s/delete$' % path_link_name.LINKNAME_ARG_PATTERN, + r'^site/sponsor/profile/%s/delete$' % soc.logic.path_link_name.LINKNAME_ARG_PATTERN, 'soc.views.site.sponsor.profile.delete'), 'Site: Delete Existing Sponsor', short_name='Delete Site Sponsor', @@ -197,7 +199,7 @@ site_sponsor_edit = page.Page( page.Url( - r'^site/sponsor/profile/%s' % path_link_name.LINKNAME_ARG_PATTERN, + r'^site/sponsor/profile/%s' % soc.logic.path_link_name.LINKNAME_ARG_PATTERN, 'soc.views.site.sponsor.profile.edit'), 'Site: Modify Existing Sponsor', short_name='Modify Site Sponsor', diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/logic/site/settings.py --- a/app/soc/logic/site/settings.py Sun Oct 12 00:08:54 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -#!/usr/bin/python2.5 -# -# Copyright 2008 the Melange authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""SiteSettings (Model) query functions. -""" - -__authors__ = [ - '"Pawel Solyga" ', - ] - -from google.appengine.ext import db - -from soc.logic import key_name - -import soc.models.site_settings -import soc.logic.model - - -def getSiteSettings(path): - """Returns SiteSettings entity for a given path, or None if not found. - - Args: - path: a request path of the SiteSettings that uniquely identifies it - """ - # lookup by Settings:path key name - name = key_name.nameSiteSettings(path) - - if name: - site_settings = soc.models.site_settings.SiteSettings.get_by_key_name(name) - else: - site_settings = None - - return site_settings - - -def updateOrCreateSiteSettings(path, **site_settings_properties): - """Update existing SiteSettings entity, or create new one with supplied properties. - - Args: - path: a request path of the SiteSettings that uniquely identifies it - **site_settings_properties: keyword arguments that correspond to Document entity - properties and their values - - Returns: - the SiteSettings entity corresponding to the path, with any supplied - properties changed, or a new SiteSettings entity now associated with the - supplied path and properties. - """ - # attempt to retrieve the existing Site Settings - site_settings = getSiteSettings(path) - - if not site_settings: - # site settings did not exist, so create one in a transaction - name = key_name.nameSiteSettings(path) - site_settings = soc.models.site_settings.SiteSettings.get_or_insert( - name, **site_settings_properties) - - # there is no way to be sure if get_or_insert() returned a new SiteSettings or - # got an existing one due to a race, so update with site_settings_properties anyway, - # in a transaction - return soc.logic.model.updateModelProperties(site_settings, **site_settings_properties) diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/logic/sponsor.py --- a/app/soc/logic/sponsor.py Sun Oct 12 00:08:54 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,150 +0,0 @@ -#!/usr/bin/python2.5 -# -# Copyright 2008 the Melange authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Sponsor (Model) query functions. -""" - -__authors__ = [ - '"Pawel Solyga" ', - ] - - -from soc.logic import key_name -from soc.logic import out_of_band - -import soc.models.sponsor -import soc.logic.model - - -def doesLinkNameExist(link_name=None): - """Returns True if link name exists in the Datastore. - - Args: - link_name: link name used in URLs to identify Sponsor - """ - if getSponsorFromLinkName(link_name): - return True - else: - return False - - -def getSponsorFromLinkName(link_name): - """Returns Sponsor entity for a given link name, or None if not found. - - Args: - link_name: a link name of the Sponsor that uniquely identifies it - """ - # lookup by Sponsor key name - sponsor_key_name = getSponsorKeyNameForLinkName(link_name) - - if sponsor_key_name: - sponsor = soc.models.sponsor.Sponsor.get_by_key_name(sponsor_key_name) - else: - sponsor = None - - return sponsor - - -def getSponsorIfLinkName(link_name=None): - """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 linkname - - 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 link_name: - # exit without error, to let view know that link_name was not supplied - return None - - linkname_sponsor = getSponsorFromLinkName(link_name=link_name) - - if linkname_sponsor: - # a Sponsor exist for this linkname, so return that Sponsor entity - return linkname_sponsor - - # else: a linkname was supplied, but there is no Sponsor that has it - raise out_of_band.ErrorResponse( - 'There is no sponsor with a "link name" of "%s".' % link_name, status=404) - - -def getSponsorKeyNameForLinkName(link_name): - """Return a Datastore key_name for a Sponsor from the link name. - - Args: - link_name: a link name of the Sponsor that uniquely identifies it - """ - if not link_name: - return None - - return key_name.nameSponsor(link_name) - - -def getSponsorsForLimitAndOffset(limit, offset=0): - """Returns Sponsors 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 = soc.models.sponsor.Sponsor.all() - return query.fetch(limit, offset) - - -def updateOrCreateSponsorFromLinkName(sponsor_link_name, **sponsor_properties): - """Update existing Sponsor entity, or create new one with supplied properties. - - Args: - sponsor_name: a linkname of the Sponsor that uniquely identifies it - **sponsor_properties: keyword arguments that correspond to Sponsor entity - properties and their values - - Returns: - the Sponsor entity corresponding to the path, with any supplied - properties changed, or a new Sponsor entity now associated with the - supplied path and properties. - """ - # attempt to retrieve the existing Sponsor - sponsor = getSponsorFromLinkName(sponsor_link_name) - - if not sponsor: - # sponsor did not exist, so create one in a transaction - sponsor_key_name = getSponsorKeyNameForLinkName(sponsor_link_name) - sponsor = soc.models.sponsor.Sponsor.get_or_insert( - sponsor_key_name, **sponsor_properties) - - # there is no way to be sure if get_or_insert() returned a new Sponsor or - # got an existing one due to a race, so update with sponsor_properties anyway, - # in a transaction - return soc.logic.model.updateModelProperties(sponsor, **sponsor_properties) - - -def deleteSponsor(sponsor): - """Delete Sponsor entity. - - Args: - sponsor: existing Sponsor entity - """ - # TODO(pawel.solyga): check if Sponsor can be deleted - # If Sponsor has Hosts or Programs it cannot be deleted - sponsor.delete() \ No newline at end of file diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/logic/works.py --- a/app/soc/logic/works.py Sun Oct 12 00:08:54 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -#!/usr/bin/python2.5 -# -# Copyright 2008 the Melange authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Works (Model) query functions. -""" - -__authors__ = [ - '"Todd Larsen" ', - ] - - -from google.appengine.ext import db - -from soc.logic import model - -import soc.models.work - - -def getWorksForLimitAndOffset(limit, offset=0, cls=soc.models.work.Work): - """Returns Works 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) - cls: Model class of items to return (including sub-classes of that type); - default is Work - """ - query = db.GqlQuery(model.buildOrderedQueryString( - soc.models.work.Work, derived_class=cls, order_by='title')) - - return query.fetch(limit, offset) diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/views/helper/responses.py --- a/app/soc/views/helper/responses.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/views/helper/responses.py Sun Oct 12 00:12:53 2008 +0000 @@ -38,6 +38,7 @@ # In the development server from google.appengine.runtime.apiproxy_errors import DeadlineExceededError +import soc.logic from soc.logic import system from soc.logic.site import id_user from soc.logic.site import sidebar @@ -64,7 +65,9 @@ Any exceptions that django.template.loader.render_to_string() or django.http.HttpResponse() might raise. """ - context = getUniversalContext(request, context=context) + + if not context: + context = getUniversalContext(request) if response_args is None: response_args = {} @@ -84,19 +87,14 @@ return http.HttpResponse('AssertionError') -def getUniversalContext(request, context=None): +def getUniversalContext(request): """Constructs a template context dict will many common variables defined. Args: request: the Django HTTP request object - context: the template context dict to be updated in-place (pass in a copy - if the original must not be modified), or None if a new one is to be - created; any existing fields already present in the context dict passed - in by the caller are left unaltered - + Returns: - updated template context dict supplied by the caller, or a new context - dict if the caller supplied None + a new context dict containing: { 'request': the Django HTTP request object passed in by the caller @@ -110,26 +108,21 @@ 'sidebar_menu_html': an HTML string that renders the sidebar menu } """ - if context is None: - context = {} + + id = users.get_current_user() + + context = {} + context['request'] = request - # set some universal values if caller did not already set them - context['request'] = context.get('request', request) - context['id'] = id_user.getIdIfMissing(context.get('id', None)) - context['user'] = id_user.getUserIfMissing(context.get('user', None), - context['id']) - context['is_admin'] = context.get( - 'is_admin', id_user.isIdDeveloper(id=context['id'])) - context['is_debug'] = context.get('is_debug', system.isDebug()) - context['sign_in'] = context.get( - 'sign_in', users.create_login_url(request.path)) - context['sign_out'] = context.get( - 'sign_out', users.create_logout_url(request.path)) + if id: + context['id'] = id + context['user'] = soc.logic.user_logic.getFromFields(email=id.email()) + context['is_admin'] = id_user.isIdDeveloper(id=id) - if not context.get('sidebar_menu_html'): - # pass the currently constructed context as keyword arguments to - # all of the sidebar builder functions - context['sidebar_menu_html'] = str(html_menu.UlMenu( + context['is_debug'] = system.isDebug() + context['sign_in'] = users.create_login_url(request.path) + context['sign_out'] = users.create_logout_url(request.path) + context['sidebar_menu_html'] = str(html_menu.UlMenu( sidebar.buildSidebar(**context))) return context diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/views/person/profile.py --- a/app/soc/views/person/profile.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/views/person/profile.py Sun Oct 12 00:12:53 2008 +0000 @@ -52,7 +52,7 @@ exclude = ['user'] -def edit(request, program=None, linkname=None, +def edit(request, program=None, link_name=None, template='soc/person/profile/edit.html'): """View for a Person to modify the properties of a Person Model. diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/views/simple.py --- a/app/soc/views/simple.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/views/simple.py Sun Oct 12 00:12:53 2008 +0000 @@ -22,6 +22,7 @@ '"Pawel Solyga" ', ] +from google.appengine.api import users from django.utils.translation import ugettext_lazy @@ -32,54 +33,44 @@ import soc.views.helper.templates -def templateWithLinkName(request, - template='soc/base.html', linkname=None, +def public(request, template='soc/base.html', link_name=None, context=None): - """A simple template view that expects a linkname extracted from the URL. + """A simple template view that expects a link_name extracted from the URL. Args: request: the standard Django HTTP request object template: the template to use for rendering the view (or a search list of templates) - linkname: a site-unique "linkname" (usually extracted from the URL) + link_name: a site-unique "link_name" (usually extracted from the URL) context: the context dict supplied to the template, which is modified (so supply a copy if such modification is not acceptable) - linkname: the linkname parameter is added to the context - linkname_user: if the linkname exists for a User, that User + link_name: the link_name parameter is added to the context + link_name_user: if the link_name exists for a User, that User is added to the context Returns: A subclass of django.http.HttpResponse containing the generated page. """ - context['linkname'] = linkname - context = helper.responses.getUniversalContext(request, context=context) + + template = helper.templates.makeSiblingTemplatesList(template, 'public.html') + + if not context: + context = helper.responses.getUniversalContext(request) try: - context['linkname_user'] = id_user.getUserIfLinkName(linkname) + if link_name: + user = id_user.getUserFromLinkNameOrDie(link_name) except out_of_band.ErrorResponse, error: return errorResponse(request, error, template, context) + context['link_name'] = link_name + context['link_name_user'] = user + return helper.responses.respond(request, template, context) -def public(request, template, linkname, context): - """A convenience wrapper around templateWithLinkName() using 'public.html'. - - Args: - request, linkname, context: see templateWithLinkName() - template: the "sibling" template (or a search list of such templates) - from which to construct the public.html template name (or names) +DEF_ERROR_TMPL = 'soc/error.html' - Returns: - A subclass of django.http.HttpResponse containing the generated page. - """ - return templateWithLinkName( - request, linkname=linkname, context=context, - template=helper.templates.makeSiblingTemplatesList( - template, 'public.html')) - - -DEF_ERROR_TMPL = 'soc/error.html' def errorResponse(request, error, template, context): """Displays an error page for an out_of_band.ErrorResponse exception. @@ -95,8 +86,10 @@ error_status: error.response_args['status'], or None if a status code was not supplied to the ErrorResponse """ - context = helper.responses.getUniversalContext(request, context=context) - + + if not context: + context = helper.responses.getUniversalContext(request) + # make a list of possible "sibling" templates, then append a default error_templates = helper.templates.makeSiblingTemplatesList( template, 'error.html', default_template=DEF_ERROR_TMPL) @@ -128,7 +121,9 @@ login_message: the caller can completely construct the message supplied to the login template in lieu of using login_message_fmt """ - context = helper.responses.getUniversalContext(request, context=context) + + if not context: + context = helper.responses.getUniversalContext(request) # make a list of possible "sibling" templates, then append a default login_templates = helper.templates.makeSiblingTemplatesList( diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/views/site/docs/edit.py --- a/app/soc/views/site/docs/edit.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/views/site/docs/edit.py Sun Oct 12 00:12:53 2008 +0000 @@ -28,7 +28,7 @@ from django import newforms as forms from django.utils.translation import ugettext_lazy -from soc.logic import document +import soc.logic from soc.logic import out_of_band from soc.logic import path_link_name from soc.logic.helper import access @@ -76,7 +76,34 @@ ugettext_lazy('Document saved.'), ) -def edit(request, partial_path=None, linkname=None, +def getDocForForm(form): + """Extracts doc fields from a form and creates a new doc from it + """ + + user = users.get_current_user() + if user: + email = user.email() + else: + email = None + + partial_path = form.cleaned_data.get('partial_path') + link_name = form.cleaned_data.get('link_name') + + properties = {} + properties['partial_path'] = partial_path + properties['link_name'] = link_name + properties['title'] = form.cleaned_data.get('title') + properties['short_name'] = form.cleaned_data.get('short_name') + properties['abstract'] = form.cleaned_data.get('abstract') + properties['content'] = form.cleaned_data.get('content') + properties['user'] = soc.logic.user_logic.getFromFields(email=email) + + doc = soc.logic.document_logic.updateOrCreateFromFields(properties, + partial_path=partial_path, link_name=link_name) + + return doc + +def edit(request, partial_path=None, link_name=None, template=DEF_SITE_DOCS_EDIT_TMPL): """View for a Developer to modify the properties of a Document Model entity. @@ -109,7 +136,9 @@ # try to fetch Document entity corresponding to path if one exists try: - doc = document.getDocumentIfPath(path) + if path: + doc = soc.logic.document_logic.getFromFields(partial_path=partial_path, + link_name=link_name) except out_of_band.ErrorResponse, error: # show custom 404 page when path doesn't exist in Datastore error.message = error.message + DEF_CREATE_NEW_DOC_MSG @@ -119,22 +148,12 @@ form = EditForm(request.POST) if form.is_valid(): - new_partial_path = form.cleaned_data.get('partial_path') - new_linkname = form.cleaned_data.get('link_name') - title = form.cleaned_data.get('title') - short_name = form.cleaned_data.get('short_name') - abstract = form.cleaned_data.get('abstract') - content = form.cleaned_data.get('content') - - doc = soc.logic.document.updateOrCreateDocument( - partial_path=new_partial_path, link_name=new_linkname, - title=title, short_name=short_name, abstract=abstract, - content=content, user=id_user.getUserFromId(logged_in_id)) + doc = getDocForForm(form) if not doc: return http.HttpResponseRedirect('/') - new_path = path_link_name.combinePath([new_partial_path, new_link_name]) + new_path = path_link_name.combinePath([doc.partial_path, doc.link_name]) # redirect to new /site/docs/edit/new_path?s=0 # (causes 'Profile saved' message to be displayed) @@ -237,17 +256,7 @@ form = CreateForm(request.POST) if form.is_valid(): - new_partial_path = form.cleaned_data.get('partial_path') - new_linkname = form.cleaned_data.get('link_name') - title = form.cleaned_data.get('title') - short_name = form.cleaned_data.get('short_name') - abstract = form.cleaned_data.get('abstract') - content = form.cleaned_data.get('content') - - doc = soc.logic.document.updateOrCreateDocument( - partial_path=new_partial_path, link_name=new_linkname, - title=title, short_name=short_name, abstract=abstract, - content=content, user=id_user.getUserFromId(logged_in_id)) + doc = getDocForForm(form) if not doc: return http.HttpResponseRedirect('/') diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/views/site/docs/list.py --- a/app/soc/views/site/docs/list.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/views/site/docs/list.py Sun Oct 12 00:12:53 2008 +0000 @@ -22,7 +22,7 @@ ] -from soc.logic import works +import soc.logic from soc.logic.helper import access from soc.views import simple from soc.views import helper @@ -59,8 +59,7 @@ offset=request.GET.get('offset'), limit=request.GET.get('limit')) # Fetch one more to see if there should be a 'next' link - docs = works.getWorksForLimitAndOffset( - limit + 1, offset=offset, cls=soc.models.document.Document) + docs = soc.logic.work_logic.getForLimitAndOffset(limit + 1, offset=offset) context['pagination_form'] = helper.lists.makePaginationForm(request, limit) diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/views/site/home.py --- a/app/soc/views/site/home.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/views/site/home.py Sun Oct 12 00:12:53 2008 +0000 @@ -33,6 +33,7 @@ from django import shortcuts from django import newforms as forms +import soc.logic from soc.logic import out_of_band from soc.logic import validate from soc.logic.site import id_user @@ -46,8 +47,6 @@ import soc.models.site_settings import soc.models.document -import soc.logic.document -import soc.logic.site.settings class DocumentForm(helper.forms.DbModelForm): @@ -107,7 +106,7 @@ # create default template context for use with any templates context = helper.responses.getUniversalContext(request) - site_settings = soc.logic.site.settings.getSiteSettings(DEF_SITE_SETTINGS_PATH) + site_settings = soc.logic.settings_logic.getFromFields(path=DEF_SITE_SETTINGS_PATH) if site_settings: context['site_settings'] = site_settings @@ -117,7 +116,7 @@ site_doc.content = helper.templates.unescape(site_doc.content) context['site_document'] = site_doc - return helper.responses.respond(request, template, context) + return helper.responses.respond(request, template, context=context) DEF_SITE_HOME_EDIT_TMPL = 'soc/site/home/edit.html' @@ -149,29 +148,37 @@ settings_form = SiteSettingsForm(request.POST) if document_form.is_valid() and settings_form.is_valid(): - title = document_form.cleaned_data.get('title') link_name = DEF_SITE_HOME_DOC_LINK_NAME - short_name = document_form.cleaned_data.get('short_name') - abstract = document_form.cleaned_data.get('abstract') - content = document_form.cleaned_data.get('content') - + partial_path=DEF_SITE_SETTINGS_PATH logged_in_id = users.get_current_user() + user = soc.logic.user_logic.getFromFields(email=logged_in_id) - site_doc = soc.logic.document.updateOrCreateDocument( - partial_path=DEF_SITE_SETTINGS_PATH, link_name=link_name, - title=title, short_name=short_name, abstract=abstract, - content=content, user=id_user.getUserFromId(logged_in_id)) + properties = {} + properties['title'] = document_form.cleaned_data.get('title') + properties['short_name'] = document_form.cleaned_data.get('short_name') + properties['abstract'] = document_form.cleaned_data.get('abstract') + properties['content'] = document_form.cleaned_data.get('content') + properties['link_name'] = link_name + properties['partial_path'] = partial_path + properties['id'] = logged_in_id + properties['user'] = user + + #bla = dir(logged_in_id) + #raise self + + site_doc = soc.logic.document_logic.updateOrCreateFromFields( + properties, partial_path=partial_path, link_name=link_name) feed_url = settings_form.cleaned_data.get('feed_url') - site_settings = soc.logic.site.settings.updateOrCreateSiteSettings( - DEF_SITE_SETTINGS_PATH, home=site_doc, feed_url=feed_url) + site_settings = soc.logic.settings_logic.updateOrCreateFromFields( + {'feed_url' : feed_url, 'home' : site_doc}, path=DEF_SITE_SETTINGS_PATH) context['notice'] = 'Site Settings saved.' else: # request.method == 'GET' # try to fetch SiteSettings entity by unique key_name - site_settings = soc.logic.site.settings.getSiteSettings( - DEF_SITE_SETTINGS_PATH) + site_settings = soc.logic.settings_logic.getFromFields( + path=DEF_SITE_SETTINGS_PATH) if site_settings: # populate form with the existing SiteSettings entity diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/views/site/sponsor/list.py --- a/app/soc/views/site/sponsor/list.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/views/site/sponsor/list.py Sun Oct 12 00:12:53 2008 +0000 @@ -22,7 +22,6 @@ ] -from soc.logic import sponsor from soc.logic.helper import access from soc.views import simple from soc.views import helper @@ -48,7 +47,7 @@ offset=request.GET.get('offset'), limit=request.GET.get('limit')) # Fetch one more to see if there should be a 'next' link - sponsors = sponsor.getSponsorsForLimitAndOffset(limit + 1, offset=offset) + sponsors = soc.logic.sponsor_logic.getForLimitAndOffset(limit + 1, offset=offset) context['pagination_form'] = helper.lists.makePaginationForm(request, limit) diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/views/site/sponsor/profile.py --- a/app/soc/views/site/sponsor/profile.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/views/site/sponsor/profile.py Sun Oct 12 00:12:53 2008 +0000 @@ -27,9 +27,9 @@ from django import http from django import newforms as forms +import soc.logic from soc.logic import validate from soc.logic import out_of_band -from soc.logic import sponsor from soc.logic.helper import access from soc.logic.site import id_user from soc.views import helper @@ -60,7 +60,7 @@ link_name = self.cleaned_data.get('link_name') if not validate.isLinkNameFormatValid(link_name): raise forms.ValidationError("This link name is in wrong format.") - if sponsor.doesLinkNameExist(link_name): + if soc.logic.sponsor_logic.getFromFields(link_name=link_name): raise forms.ValidationError("This link name is already in use.") return link_name @@ -106,13 +106,13 @@ context = helper.responses.getUniversalContext(request) logged_in_id = users.get_current_user() - user = id_user.getUserFromId(logged_in_id) + user = soc.logic.user_logic.getFromFields(email=logged_in_id) sponsor_form = None existing_sponsor = None # try to fetch Sponsor entity corresponding to link_name if one exists try: - existing_sponsor = soc.logic.sponsor.getSponsorIfLinkName(linkname) + existing_sponsor = soc.logic.sponsor_logic.getIfFields(link_name=link_name) except out_of_band.ErrorResponse, error: # show custom 404 page when link name doesn't exist in Datastore error.message = error.message + DEF_CREATE_NEW_SPONSOR_MSG @@ -144,8 +144,7 @@ fields['founder'] = user form_ln = fields['link_name'] - form_sponsor = sponsor.updateOrCreateSponsorFromLinkName(form_ln, - **fields) + form_sponsor = soc.logic.sponsor_logic.updateOrCreateFromFields(fields, link_name=form_ln) if not form_sponsor: return http.HttpResponseRedirect('/') diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/views/site/user/list.py --- a/app/soc/views/site/user/list.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/views/site/user/list.py Sun Oct 12 00:12:53 2008 +0000 @@ -22,6 +22,7 @@ ] +import soc.logic from soc.logic.helper import access from soc.logic.site import id_user from soc.views import simple @@ -59,7 +60,7 @@ offset=request.GET.get('offset'), limit=request.GET.get('limit')) # Fetch one more to see if there should be a 'next' link - users = id_user.getUsersForLimitAndOffset(limit + 1, offset=offset) + users = soc.logic.user_logic.getForLimitAndOffset(limit + 1, offset=offset) context['pagination_form'] = helper.lists.makePaginationForm(request, limit) diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/views/site/user/profile.py --- a/app/soc/views/site/user/profile.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/views/site/user/profile.py Sun Oct 12 00:12:53 2008 +0000 @@ -28,6 +28,7 @@ from django import newforms as forms from django.utils.translation import ugettext_lazy +import soc.logic from soc.logic import validate from soc.logic import out_of_band from soc.logic.helper import access @@ -126,7 +127,7 @@ if form_id: # email provided, so attempt to look up user by email - user = id_user.getUserFromId(form_id) + user = soc.logic.user_logic.getFromFields(id=form_id) if user: lookup_message = ugettext_lazy('User found by email.') @@ -166,7 +167,7 @@ if user: # User entity found, so populate form with existing User information # context['found_user'] = user - form = LookupForm(initial={'id': user.id.email, + form = LookupForm(initial={'id': user.id.email(), 'link_name': user.link_name}) if request.path.endswith('lookup'): @@ -218,11 +219,12 @@ link_name = self.cleaned_data.get('link_name') if not validate.isLinkNameFormatValid(link_name): raise forms.ValidationError("This link name is in wrong format.") - else: - key_name = self.data.get('key_name') - if not id_user.isLinkNameAvailableForId( - link_name, id=id_user.getUserFromKeyName(key_name).id) : - raise forms.ValidationError("This link name is already in use.") + + user = soc.logic.user_logic.getFromKeyName(link_name) + + if user and user.link_name != link_name: + raise forms.ValidationError("This link name is already in use.") + return link_name def clean_id(self): @@ -312,7 +314,7 @@ # populate form with the existing User entity form = EditForm(initial={'key_name': user.key().name(), - 'id': user.id.email, 'link_name': user.link_name, + 'id': user.id.email(), 'link_name': user.link_name, 'nick_name': user.nick_name, 'is_developer': user.is_developer}) else: if request.GET.get(profile.SUBMIT_MSG_PARAM_NAME): @@ -367,14 +369,14 @@ if not validate.isLinkNameFormatValid(link_name): raise forms.ValidationError("This link name is in wrong format.") else: - if id_user.doesLinkNameExist(link_name): + if id_user.getUserFromLinkName(link_name): raise forms.ValidationError("This link name is already in use.") return link_name def clean_id(self): new_email = self.cleaned_data.get('id') form_id = users.User(email=new_email) - if id_user.isIdUser(form_id): + if soc.logic.user_logic.getFromFields(email=form_id): raise forms.ValidationError("This account is already in use.") return form_id @@ -407,21 +409,23 @@ if form.is_valid(): form_id = form.cleaned_data.get('id') - new_linkname = form.cleaned_data.get('link_name') - nickname = form.cleaned_data.get('nick_name') - is_developer = form.cleaned_data.get('is_developer') + link_name = form.cleaned_data.get('link_name') - user = id_user.updateOrCreateUserFromId(id=form_id, - link_name=new_linkname, nick_name=nickname, - is_developer=is_developer) + properties = {} + properties['id'] = form_id + properties['link_name'] = link_name + properties['nick_name'] = form.cleaned_data.get('nick_name') + properties['is_developer'] = form.cleaned_data.get('is_developer') + + user = soc.logic.user_logic.updateOrCreateFromFields(properties, email=form_id) if not user: return http.HttpResponseRedirect('/') - # redirect to new /site/user/profile/new_linkname?s=0 + # redirect to new /site/user/profile/new_link_name?s=0 # (causes 'Profile saved' message to be displayed) return helper.responses.redirectToChangedSuffix( - request, None, new_linkname, + request, None, link_name, params=profile.SUBMIT_PROFILE_SAVED_PARAMS) else: # method == 'GET': # no link name specified, so start with an empty form diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/views/user/profile.py --- a/app/soc/views/user/profile.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/views/user/profile.py Sun Oct 12 00:12:53 2008 +0000 @@ -28,6 +28,7 @@ from django import newforms as forms from django.utils.translation import ugettext_lazy +import soc.logic from soc.logic import validate from soc.logic import out_of_band from soc.logic.site import id_user @@ -56,8 +57,12 @@ link_name = self.cleaned_data.get('link_name') if not validate.isLinkNameFormatValid(link_name): raise forms.ValidationError("This link name is in wrong format.") - elif not id_user.isLinkNameAvailableForId(link_name): + + user = id_user.getUserFromLinkName(link_name) + + if user and not id_user.doesLinkNameBelongToId(link_name, user.id): raise forms.ValidationError("This link name is already in use.") + return link_name @@ -109,7 +114,8 @@ # try to fetch User entity corresponding to link_name if one exists try: - linkname_user = id_user.getUserIfLinkName(linkname) + if link_name: + link_name_user = id_user.getUserFromLinkNameOrDie(link_name) except out_of_band.ErrorResponse, error: # show custom 404 page when link name doesn't exist in Datastore return simple.errorResponse(request, error, template, context) @@ -124,19 +130,21 @@ form = UserForm(request.POST) if form.is_valid(): - new_linkname = form.cleaned_data.get('link_name') - nickname = form.cleaned_data.get("nick_name") + new_link_name = form.cleaned_data.get('link_name') + properties = {} + properties['link_name'] = new_link_name + properties['nick_name'] = form.cleaned_data.get("nick_name") + properties['id'] = id - user = id_user.updateOrCreateUserFromId( - id, link_name=new_linkname, nick_name=nickname) + user = soc.logic.user_logic.updateOrCreateFromFields(properties, email=id) # redirect to new /user/profile/new_link_name?s=0 # (causes 'Profile saved' message to be displayed) return helper.responses.redirectToChangedSuffix( request, link_name, new_link_name, params=SUBMIT_PROFILE_SAVED_PARAMS) else: # request.method == 'GET' - # try to fetch User entity corresponding to Google Account if one exists - user = id_user.getUserFromId(id) + # try to fetch User entity corresponding to Google Account if one exists + user = soc.logic.user_logic.getFromFields(email=id) if user: # is 'Profile saved' parameter present, but referrer was not ourself? diff -r c76a366c7ab4 -r a1cc853a56e5 app/soc/views/user/roles.py --- a/app/soc/views/user/roles.py Sun Oct 12 00:08:54 2008 +0000 +++ b/app/soc/views/user/roles.py Sun Oct 12 00:12:53 2008 +0000 @@ -72,7 +72,7 @@ """ #TODO(tlarsen): this module is currently a placeholder for future work - # TODO: if linkname is empty or not a valid linkname on the site, display + # TODO: if link_name is empty or not a valid link_name on the site, display # some sort of "user does not exist" page (a custom 404 page, maybe?). return response_helpers.respond(request,