--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/soc/views/models/base.py Thu Oct 16 23:23:16 2008 +0000
@@ -0,0 +1,356 @@
+#!/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.
+
+"""Helpers functions for displaying views.
+"""
+
+__authors__ = [
+ '"Todd Larsen" <tlarsen@google.com>',
+ '"Sverre Rabbelier" <sverer@rabbelier.nl>',
+ '"Pawel Solyga" <pawel.solyga@gmail.com>',
+ ]
+
+
+from django import http
+from django.utils.translation import ugettext_lazy
+
+import soc.logic
+import soc.logic.out_of_band
+import soc.views.helper.lists
+import soc.views.helper.responses
+import soc.views.out_of_band
+
+from soc.logic import models
+from soc.logic import validate
+from soc.views import simple
+from soc.views import helper
+from soc.views.helper import access
+
+
+class View:
+ """Views for entity classes.
+
+ The View class functions specific to Entity classes by relying
+ on the the child-classes to define the following fields:
+
+ self._logic: the logic singleton for this entity
+
+ Args:
+ rights: This dictionary should be filled with the access check
+ functions that should be called
+
+ params: This dictionary should be filled with the parameters
+ specific to this entity.
+ """
+
+ def __init__(self, params=None, rights=None):
+ """
+ """
+
+ new_rights = {}
+ new_rights['base'] = [access.checkIsLoggedIn]
+
+ self._rights = soc.logic.dicts.mergeDicts(rights, new_rights)
+ self._params = params
+
+ self.DEF_SUBMIT_MSG_PARAM_NAME = 's'
+
+ self.DEF_CREATE_NEW_ENTITY_MSG = ugettext_lazy(
+ ' You can create a new %(model_type)s by visiting'
+ ' <a href="%(create)s">Create '
+ 'a New %(Type)s</a> page.')
+
+ def public(self, request, **kwargs):
+ """Displays the public page for the entity specified by **kwargs
+
+ Args:
+ request: the Django request object
+ kwargs: the Key Fields for the specified entity
+ """
+
+ try:
+ self.checkAccess('edit', request)
+ except soc.views.out_of_band.AccessViolationResponse, alt_response:
+ return alt_response.response()
+
+ # create default template context for use with any templates
+ context = helper.responses.getUniversalContext(request)
+ entity = None
+
+ try:
+ entity = self._logic.getIfFields(**kwargs)
+ except soc.logic.out_of_band.ErrorResponse, error:
+ template = soc._params['public_template']
+ return simple.errorResponse(request, error, template, context)
+
+ if not entity:
+ #TODO: Change this into a proper redirect
+ return http.HttpResponseRedirect('/')
+
+ self._makePublic(entity)
+
+ context['entity'] = entity
+ context['entity_type'] = self._params['name']
+
+ template = self._params['public_template']
+
+ return helper.responses.respond(request, template, context)
+
+ def create(self, request, **kwargs):
+ """Displays the create page for this entity type
+
+ request: the django request object
+ kwargs: not used
+ """
+
+ # Create page is an edit page with no key fields
+ kwargs = {}
+ return self.edit(request, **kwargs)
+
+ def edit(self, request, **kwargs):
+ """Displays the public page for the entity specified by **kwargs
+
+ Args:
+ request: The Django request object
+ kwargs: The Key Fields for the specified entity
+ """
+
+ try:
+ self.checkAccess('edit', request)
+ except soc.views.out_of_band.AccessViolationResponse, alt_response:
+ return alt_response.response()
+
+ entity = None
+
+ try:
+ entity = self._logic.getIfFields(**kwargs)
+ except soc.logic.out_of_band.ErrorResponse, error:
+ template = soc._params['public_template']
+ error.message = error.message + self.DEF_CREATE_NEW_ENTITY_MSG % {
+ 'entity_type_lower' : self._params['name_lower'],
+ 'entity_type_upper' : self._parmas['name_upper'],
+ 'create' : self._redirects['create']
+ }
+ return simple.errorResponse(request, error, template, context)
+
+ if request.method == 'POST':
+ return self.editPost(request, entity)
+ else:
+ return self.editGet(request, entity)
+
+ def editPost(self, request, entity):
+ """Same as edit, but on POST
+ """
+
+ context = helper.responses.getUniversalContext(request)
+
+ if entity:
+ form = self._params['edit_form'](request.POST)
+ else:
+ form = self._params['create_form'](request.POST)
+
+ if not form.is_valid():
+ return
+
+ fields = self.collectCleanedFields(form)
+
+ self._editPost(request, entity, fields)
+
+ keys = self._logic.extractKeyFields(fields)
+ entity = self._logic.updateOrCreateFromFields(fields, **keys)
+
+ if not entity:
+ return http.HttpResponseRedirect('/')
+
+ params=self._params['edit_params']
+ #TODO(SRabbelier) Construct a suffix
+ suffix = None
+
+ # redirect to (possibly new) location of the entity
+ # (causes 'Profile saved' message to be displayed)
+ return helper.responses.redirectToChangedSuffix(
+ request, None, suffix,
+ params=params)
+
+ def editGet(self, request, entity):
+ """Same as edit, but on GET
+ """
+
+ context = helper.responses.getUniversalContext(request)
+ #TODO(SRabbelier) Construct a suffix
+ suffix = None
+ is_self_referrer = helper.requests.isReferrerSelf(request, suffix=suffix)
+
+ # Remove the params from the request, this is relevant only if
+ # someone bookmarked a POST page.
+ if request.GET.get(self.DEF_SUBMIT_MSG_PARAM_NAME):
+ if (not entity) or (not is_self_referrer):
+ return http.HttpResponseRedirect(request.path)
+
+ if entity:
+ # Note: no message will be displayed if parameter is not present
+ context['notice'] = helper.requests.getSingleIndexedParamValue(
+ request,
+ self.DEF_SUBMIT_MSG_PARAM_NAME,
+ values=self._params['save_message'])
+
+ # populate form with the existing entity
+ form = self._params['edit_form'](instance=entity)
+ else:
+ form = self._params['create_form']()
+
+ context['form'] = form
+ context['entity'] = entity
+ context['entity_type'] = self._params['name']
+ context['entity_type_plural'] = self._params['name_plural']
+
+ template = self._params['create_template']
+
+ return helper.responses.respond(request, template, context)
+
+ def list(self, request):
+ """Displays the list page for the entity type
+ """
+
+ try:
+ self.checkAccess('list', request)
+ except soc.views.out_of_band.AccessViolationResponse, alt_response:
+ return alt_response.response()
+
+ context = helper.responses.getUniversalContext(request)
+
+ offset, limit = helper.lists.cleanListParameters(
+ offset=request.GET.get('offset'), limit=request.GET.get('limit'))
+
+ # Fetch one more to see if there should be a 'next' link
+ entities = self._logic.getForLimitAndOffset(limit + 1, offset=offset)
+
+ context['pagination_form'] = helper.lists.makePaginationForm(request, limit)
+
+ templates = self._params['lists_template']
+
+ context = helper.lists.setList(request, context, entities,
+ offset, limit, templates)
+
+ context['entity_type'] = self._params['name']
+ context['entity_type_plural'] = self._params['name_plural']
+
+ template = self._params['list_template']
+
+ return helper.responses.respond(request, template, context)
+
+ def delete(self, request, **kwargs):
+ """Shows the delete page for the entity specified by kwargs
+
+ Args:
+ request: The Django request object
+ kwargs: The Key Fields for the specified entity
+ """
+
+ try:
+ self.checkAccess('delete', request)
+ except soc.views.out_of_band.AccessViolationResponse, alt_response:
+ return alt_response.response()
+
+ # create default template context for use with any templates
+ context = helper.responses.getUniversalContext(request)
+ entity = None
+
+ try:
+ entity = models.sponsor.logic.getIfFields(**kwargs)
+ except soc.logic.out_of_band.ErrorResponse, error:
+ template = self._templates['create']
+ error.message = error.message + DEF_CREATE_NEW_ENTITY_MSG % {
+ 'entity_type_lower' : self._name,
+ 'entity_type_upper' : self._Name,
+ 'create' : self._redirects['create']
+ }
+ return simple.errorResponse(request, error, template, context)
+
+ if not entity:
+ #TODO: Create a proper error page for this
+ return http.HttpResponseRedirect('/')
+
+ if not self._logic.isDeletable(entity):
+ # TODO: Direct user to page telling them they can't delete that entity, and why
+ pass
+
+ self._logic.delete(entity)
+ redirect = self._params['delete_redirect']
+
+ return http.HttpResponseRedirect(redirect)
+
+ def _editPost(self, request, entity, fields):
+ """Performs any required processing on the entity to post its edit page
+
+ Args:
+ request: The django request object
+ entity: the entity to make public
+ fields: The new field values
+ """
+
+ pass
+
+ def checkUnspecified(self, access_type, request):
+ """Checks whether an unspecified access_type should be allowed
+
+ Args:
+ access_type: the access type (such as 'list' or 'edit') that was
+ not present in the _rights dictionary when checking.
+ """
+
+ pass
+
+ def checkAccess(self, access_type, request):
+ """Runs all the defined checks for the specified type
+
+ Args:
+ access_type: the type of request (such as 'list' or 'edit')
+ request: the Django request object
+
+ Returns:
+ True: If all the required access checks have been made successfully
+ False: If a check failed, in this case self._response will contain
+ the response provided by the failed access check.
+ """
+
+ if access_type not in self._rights:
+ self.checkUnspecified(access_type, request)
+ return
+
+ # Call each access checker
+ for check in self._rights['base']:
+ check(request)
+
+ for check in self._rights[access_type]:
+ check(request)
+
+ # All checks were successfull
+ return
+
+ def collectCleanedFields(self, form):
+ """Collects all cleaned fields from form and returns them
+
+ Args:
+ form: The form from which the cleaned fields should be collected
+ """
+
+ fields = {}
+
+ for field, value in form.cleaned_data.iteritems():
+ fields[field] = value
+
+ return fields