# HG changeset patch # User Todd Larsen # Date 1211387255 0 # Node ID 8b43c541afa7afcb9786bf7d3274f77cd587ffe5 # Parent 636baa95715c5f6253ec51b4269de9d290a1079e First iteration of a "prototype" Melange app, along with an initial Person Profile view. Patch by: Augie Fackler (with some additions by Todd Larsen) Review by: Todd Larsen Review issue: 46 Review URL: http://codereviews.googleopensourceprograms.com/46 diff -r 636baa95715c -r 8b43c541afa7 apps/proto/app.yaml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/apps/proto/app.yaml Wed May 21 16:27:35 2008 +0000 @@ -0,0 +1,27 @@ +# 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. + +# TODO(proto): uncomment and supply a Google App Engine application instance +# application: FIXME +version: 1 +runtime: python +api_version: 1 + +handlers: +- url: /content + static_dir: content + +- url: /.* + script: main.py + diff -r 636baa95715c -r 8b43c541afa7 apps/proto/content/logo.jpg Binary file apps/proto/content/logo.jpg has changed diff -r 636baa95715c -r 8b43c541afa7 apps/proto/content/proto.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/apps/proto/content/proto.css Wed May 21 16:27:35 2008 +0000 @@ -0,0 +1,20 @@ +/* +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. + */ + +body { + font-family: Verdana, Helvetica, sans-serif; + background-color: #DDDDDD; +} diff -r 636baa95715c -r 8b43c541afa7 apps/proto/main.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/apps/proto/main.py Wed May 21 16:27:35 2008 +0000 @@ -0,0 +1,73 @@ +#!/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. + +__authors__ = [ + # alphabetical order by last name, please + '"Augie Fackler" ', + ] + + +import logging +import os +import sys + +from google.appengine.ext.webapp import util + + +# Remove the standard version of Django. +for k in [k for k in sys.modules if k.startswith('django')]: + del sys.modules[k] + +# Force sys.path to have our own directory first, in case we want to import +# from it. This lets us replace the built-in Django +sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) + +# Force Django to reload its settings. +from django.conf import settings +settings._target = None + +# Must set this env var before importing any part of Django +os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' + +import django.core.handlers.wsgi +import django.core.signals +import django.db +import django.dispatch.dispatcher + + +# Log errors. +def log_exception(*args, **kwds): + logging.exception('Exception in request:') + +django.dispatch.dispatcher.connect( + log_exception, django.core.signals.got_request_exception) + +# Unregister the rollback event handler. +django.dispatch.dispatcher.disconnect( + django.db._rollback_on_exception, + django.core.signals.got_request_exception) + + +def main(): + # Create a Django application for WSGI. + application = django.core.handlers.wsgi.WSGIHandler() + + # Run the WSGI CGI handler with that application. + util.run_wsgi_app(application) + + +if __name__ == '__main__': + main() diff -r 636baa95715c -r 8b43c541afa7 apps/proto/settings.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/apps/proto/settings.py Wed May 21 16:27:35 2008 +0000 @@ -0,0 +1,105 @@ +# 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. + +__authors__ = [ + '"Augie Fackler" ', + ] + + +import os + + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS + +# 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. +DATABASE_ENGINE = 'dummy' +# None of the following are used with appengine +DATABASE_NAME = '' # Or path to database file if using sqlite3. +DATABASE_USER = '' # Not used with sqlite3. +DATABASE_PASSWORD = '' # Not used with sqlite3. +# Set to empty string for localhost. Not used with sqlite3. +DATABASE_HOST = '' +# Set to empty string for default. Not used with sqlite3. +DATABASE_PORT = '' + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'UTC' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash if there is a path component (optional in other cases). +# Examples: "http://media.lawrence.com", "http://example.com/media/" +MEDIA_URL = '' + +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a +# trailing slash. +# Examples: "http://foo.com/media/", "/media/". +ADMIN_MEDIA_PREFIX = '/media/' + +# TODO Make this unique, and don't share it with anybody. +SECRET_KEY = 'hvhxfm5u=^*v&doo#oq8x*eg8+1&9sxbye@=umutgn^t_sg_nx' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.load_template_source', + 'django.template.loaders.app_directories.load_template_source', +# 'django.template.loaders.eggs.load_template_source', +) + +MIDDLEWARE_CLASSES = ( +# 'django.middleware.common.CommonMiddleware', +# 'django.contrib.sessions.middleware.SessionMiddleware', +# 'django.contrib.auth.middleware.AuthenticationMiddleware', +# 'django.middleware.doc.XViewMiddleware', +) + +ROOT_URLCONF = 'urls' + +ROOT_PATH = os.path.dirname(__file__) +TEMPLATE_DIRS = ( + # TODO(proto): customize the template search directories + os.path.join(ROOT_PATH, 'proto', 'templates'), + os.path.join(ROOT_PATH, 'soc', 'templates'), +) + +INSTALLED_APPS = ( +# 'django.contrib.auth', +# 'django.contrib.contenttypes', +# 'django.contrib.sessions', +# 'django.contrib.sites', +) diff -r 636baa95715c -r 8b43c541afa7 apps/proto/urls.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/apps/proto/urls.py Wed May 21 16:27:35 2008 +0000 @@ -0,0 +1,27 @@ +# 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. + +__authors__ = [ + '"Augie Fackler" ', + ] + + +from django.conf.urls.defaults import * + + +urlpatterns = patterns( + '', + (r'^person/profile/$', 'soc.views.person.profile', + {'template': 'proto/profile.html'}), +) diff -r 636baa95715c -r 8b43c541afa7 soc/templates/soc/profile.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/soc/templates/soc/profile.html Wed May 21 16:27:35 2008 +0000 @@ -0,0 +1,30 @@ +{% comment %} +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. +{% endcomment %} + + + + Profile + {% block 'stylesheet' %}{% endblock %} + + +

+ {% block 'logo' %}{% endblock %} + Welcome, {{user.nickname}}. Please update your profile: +

+ {{form.as_table}}
+ +
+

+ + diff -r 636baa95715c -r 8b43c541afa7 soc/views/person.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/soc/views/person.py Wed May 21 16:27:35 2008 +0000 @@ -0,0 +1,65 @@ +#!/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. + +"""Views relevant to the Person role. +""" + +__authors__ = [ + '"Augie Fackler" ', + ] + + +from google.appengine.api import users +from google.appengine.ext.db import djangoforms +from django import http +from django import shortcuts +from django import newforms as forms + +from soc.models import person + + +class ProfileForm(djangoforms.ModelForm): + class Meta: + """Inner Meta class that defines some behavior for the form. + + """ + #: the db.Model subclass for which the form will gather information. + model = person.Person + #: the list of model fields which will *not* be gathered by the form. + exclude = ['user', ] + + +def profile(request, template='soc/profile.html'): + """View for a Person to modify the properties of a PersonModel. + + Args: + request: the standard django request object. + template: the template path to use for rendering the template. + + Returns: + A subclass of django.http.HttpResponse which either contains the form to + be filled out, or a redirect to the correct view in the interface. + """ + user = users.get_current_user() + if not user: + return http.HttpResponseRedirect(users.create_login_url(request.path)) + form = ProfileForm() + if request.method=='POST': + form = ProfileForm(request.POST) + if not form.errors: + return http.HttpResponse('This would update the model') + return shortcuts.render_to_response( + template, dictionary={'template': template, 'form': form, 'user': user})