[cig-commits] r7784 - in cs/pythia/trunk: cig/web/seismo/events
opal/components opal/conf/urls opal/core/handlers opal/db opal/views
leif at geodynamics.org
leif at geodynamics.org
Tue Aug 7 20:37:44 PDT 2007
Author: leif
Date: 2007-08-07 20:37:43 -0700 (Tue, 07 Aug 2007)
New Revision: 7784
Added:
cs/pythia/trunk/cig/web/seismo/events/components.py
cs/pythia/trunk/cig/web/seismo/events/parsers.py
Removed:
cs/pythia/trunk/cig/web/seismo/events/urls.py
cs/pythia/trunk/cig/web/seismo/events/views.py
cs/pythia/trunk/opal/conf/urls/defaults.py
Modified:
cs/pythia/trunk/opal/components/WebComponent.py
cs/pythia/trunk/opal/components/__init__.py
cs/pythia/trunk/opal/core/handlers/base.py
cs/pythia/trunk/opal/db/queries.py
cs/pythia/trunk/opal/views/defaults.py
Log:
Using 'events' as a guiding example, I began replacing Django's
"module oriented" application interface with something more
object-oriented, so that I can avoid global variables/functions and
use novel things like inheritance and polymorphism.
Simplified 'queries': collapsed the Query class cluster into a single
class, and added the factory class Inquirer.
Added: cs/pythia/trunk/cig/web/seismo/events/components.py
===================================================================
--- cs/pythia/trunk/cig/web/seismo/events/components.py 2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/cig/web/seismo/events/components.py 2007-08-08 03:37:43 UTC (rev 7784)
@@ -0,0 +1,228 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+# cig.web.seismo.events
+#
+# Copyright (c) 2007, California Institute of Technology
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+#
+# * Neither the name of the California Institute of Technology nor
+# the names of its contributors may be used to endorse or promote
+# products derived from this software without specific prior
+# written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+from models import Event, Source, DataSource, Region
+from parsers import HarvardCMTSearchResultsParser
+
+from cig.seismo.events import CMTSolution
+from opal import forms
+from opal.http import HttpResponseRedirect
+from opal.shortcuts import render_to_response
+from opal.template.context import RequestContext
+
+
+class EventBrowser(WebComponent):
+
+
+ models = [Event, Source, DataSource, Region]
+
+
+ def __init__(self, home):
+
+ self.home = home # '/specfem3dglobe/events/'
+
+ self.urlpatterns = self.patterns(
+ (r'^$', self.eventList),
+ (r'^search/$', self.eventSearch),
+ (r'^add/$', self.addEvent),
+ (r'^upload/$', self.uploadEvent),
+ (r'^sources/(?P<object_id>\d+)/$', self.sourceDetail),
+ (r'^sources/(?P<object_id>\d+)/edit/$', self.editSource),
+ (r'^sources/(?P<object_id>\d+)/delete/$', self.deleteSource),
+ (r'^(?P<object_id>\d+)/$', self.eventDetail),
+ (r'^(?P<object_id>\d+)/edit/$', self.editEvent),
+ (r'^(?P<object_id>\d+)/delete/$', self.deleteEvent),
+ )
+
+ return
+
+
+ # views
+
+ def eventList(self, request):
+ return self.genericObjectList(
+ request,
+ queryset = Event.user_objects.all(),
+ allow_empty = True,
+ )
+
+
+ def eventDetail(self, request):
+ return self.genericObjectDetail(
+ request,
+ queryset = Event.user_objects.all()
+ )
+
+
+ def editEvent(self, request):
+ return self.genericUpdateObject(
+ request,
+ model = Event,
+ post_save_redirect = self.home,
+ follow: { 'user': False },
+ )
+
+
+ def deleteEvent(self, request):
+ return self.genericDeleteObject(
+ request,
+ model: Event,
+ post_delete_redirect: self.home,
+ )
+
+
+ def eventSearch(self, request):
+ import urllib2
+
+ if request.method == 'GET':
+ return render_to_response('events/event_search.html',
+ {},
+ RequestContext(request, {}))
+
+ # Simply forward the search request to Harvard.
+ query = request.POST.urlencode()
+ url = "http://www.seismology.harvard.edu/cgi-bin/CMT3/form?" + query
+ src = urllib2.urlopen(url)
+
+ # Parse the results.
+ parser = HarvardCMTSearchResultsParser()
+ parser.feed(src.read())
+
+ parser.close()
+ src.close()
+
+ # Make sure secondary objects exist in the database.
+ for event in parser.cmtList:
+ # The try-get()-except shouldn't be necessary, but simply
+ # using save() causes Django to die in the database backend.
+ try:
+ ds = DataSource.objects.get(name=event.dataSource)
+ except DataSource.DoesNotExist:
+ ds = DataSource(event.dataSource)
+ ds.save()
+ try:
+ ds = Region.objects.get(name=event.regionName)
+ except:
+ r = Region(event.regionName)
+ r.save()
+
+ return render_to_response('events/event_search_results.html',
+ {'event_list': parser.cmtList },
+ RequestContext(request, {}))
+
+
+ def addEvent(self, request):
+ from forms import AddSingleSourceEventManipulator
+ from os.path import dirname
+
+ manipulator = AddSingleSourceEventManipulator()
+
+ if request.method == 'POST':
+ new_data = request.POST.copy()
+ errors = manipulator.get_validation_errors(new_data)
+ if not errors:
+ manipulator.do_html2python(new_data)
+ new_event = manipulator.save(new_data, request.user)
+ url = "%s/%i/" % (dirname(dirname(request.path)), new_event.id)
+ return HttpResponseRedirect(url)
+ else:
+ errors = new_data = {}
+
+ form = forms.FormWrapper(manipulator, new_data, errors)
+ return render_to_response('events/single_source_event_form.html',
+ {'form': form},
+ RequestContext(request, {}))
+
+
+ def uploadEvent(self, request):
+ from forms import UploadEventManipulator
+ from os.path import dirname
+
+ manipulator = UploadEventManipulator()
+
+ if request.method == 'POST':
+ new_data = request.POST.copy()
+ new_data.update(request.FILES)
+ errors = manipulator.get_validation_errors(new_data)
+ if not errors:
+ manipulator.do_html2python(new_data)
+ new_event = manipulator.save(new_data, request.user)
+ url = "%s/%i/" % (dirname(dirname(request.path)), new_event.id)
+ return HttpResponseRedirect(url)
+ else:
+ errors = new_data = {}
+
+ form = forms.FormWrapper(manipulator, new_data, errors)
+ return render_to_response('events/event_upload.html',
+ {'form': form},
+ RequestContext(request, {}))
+
+
+ # views -- sources
+
+ def sourceDetail(self, request):
+ return self.genericObjectDetail(
+ request,
+ queryset = Source.objects.all()
+ )
+
+
+ def editSource(self, request):
+ return self.genericUpdateObject(
+ request,
+ model = Source,
+ post_save_redirect = self.home,
+ follow: { 'user': False },
+ )
+
+
+ def deleteSource(self, request):
+ return self.genericDeleteObject(
+ request,
+ model: Source,
+ post_delete_redirect: self.home,
+ )
+
+
+# end of file
Copied: cs/pythia/trunk/cig/web/seismo/events/parsers.py (from rev 7782, cs/pythia/trunk/cig/web/seismo/events/views.py)
===================================================================
--- cs/pythia/trunk/cig/web/seismo/events/views.py 2007-08-07 21:45:19 UTC (rev 7782)
+++ cs/pythia/trunk/cig/web/seismo/events/parsers.py 2007-08-08 03:37:43 UTC (rev 7784)
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+# cig.web.seismo.events
+#
+# Copyright (c) 2006, California Institute of Technology
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+#
+# * Neither the name of the California Institute of Technology nor
+# the names of its contributors may be used to endorse or promote
+# products derived from this software without specific prior
+# written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+from HTMLParser import HTMLParser
+
+
+class HarvardCMTSearchResultsParser(HTMLParser):
+
+ def __init__(self):
+ HTMLParser.__init__(self)
+ self.state = 0
+ self.cmtList = None
+
+ def handle_starttag(self, tag, attrs):
+ if self.state == 0:
+ if tag == 'body':
+ self.state = 1
+ elif self.state == 2:
+ if tag == 'pre':
+ self.state = 3
+ return
+
+ def handle_endtag(self, tag):
+ if tag == 'body':
+ self.state = 0
+ elif self.state == 3:
+ if tag == 'pre':
+ self.state = 1
+ return
+
+ def handle_data(self, data):
+ if self.state == 1:
+ if data.find('Output in CMTSOLUTION format') != -1:
+ self.state = 2
+ elif self.state == 3:
+ self.cmtList = CMTSolution.parse(data)
+ return
+
+
+# end of file
Deleted: cs/pythia/trunk/cig/web/seismo/events/urls.py
===================================================================
--- cs/pythia/trunk/cig/web/seismo/events/urls.py 2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/cig/web/seismo/events/urls.py 2007-08-08 03:37:43 UTC (rev 7784)
@@ -1,98 +0,0 @@
-#!/usr/bin/env python
-#
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#
-# cig.web.seismo.events
-#
-# Copyright (c) 2006, California Institute of Technology
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following
-# disclaimer in the documentation and/or other materials provided
-# with the distribution.
-#
-# * Neither the name of the California Institute of Technology nor
-# the names of its contributors may be used to endorse or promote
-# products derived from this software without specific prior
-# written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#
-
-
-from opal.conf.urls.defaults import *
-from models import Event, Source
-
-
-event_list_detail_args = {
- 'queryset': Event.user_objects.all(),
- 'allow_empty': True,
-}
-
-event_detail_args = {
- 'queryset': Event.user_objects.all(),
-}
-
-event_create_update_args = {
- 'model': Event,
- 'post_save_redirect': '/specfem3dglobe/events/',
- 'follow': { 'user': False },
- }
-
-event_delete_args = {
- 'model': Event,
- 'post_delete_redirect': '/specfem3dglobe/events/',
- }
-
-source_detail_args = {
- 'queryset': Source.objects.all(),
-}
-
-source_create_update_args = {
- 'model': Source,
- 'post_save_redirect': '/specfem3dglobe/events/',
- }
-
-source_delete_args = {
- 'model': Source,
- 'post_delete_redirect': '/specfem3dglobe/events/',
- }
-
-
-urlpatterns = patterns('',
- (r'^$', 'opal.views.generic.list_detail.object_list', event_list_detail_args),
- (r'^search/$', 'cig.web.seismo.events.views.search'),
- (r'^add/$', 'cig.web.seismo.events.views.add'),
- (r'^upload/$', 'cig.web.seismo.events.views.upload'),
- (r'^sources/(?P<object_id>\d+)/$', 'opal.views.generic.list_detail.object_detail', source_detail_args),
- (r'^sources/(?P<object_id>\d+)/edit/$', 'opal.views.generic.create_update.update_object', source_create_update_args),
- (r'^sources/(?P<object_id>\d+)/delete/$', 'opal.views.generic.create_update.delete_object', source_delete_args),
- (r'^(?P<object_id>\d+)/$', 'opal.views.generic.list_detail.object_detail', event_detail_args),
- (r'^(?P<object_id>\d+)/edit/$', 'opal.views.generic.create_update.update_object', event_create_update_args),
- (r'^(?P<object_id>\d+)/delete/$', 'opal.views.generic.create_update.delete_object', event_delete_args),
-)
-
-
-# end of file
Deleted: cs/pythia/trunk/cig/web/seismo/events/views.py
===================================================================
--- cs/pythia/trunk/cig/web/seismo/events/views.py 2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/cig/web/seismo/events/views.py 2007-08-08 03:37:43 UTC (rev 7784)
@@ -1,178 +0,0 @@
-#!/usr/bin/env python
-#
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#
-# cig.web.seismo.events
-#
-# Copyright (c) 2006, California Institute of Technology
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following
-# disclaimer in the documentation and/or other materials provided
-# with the distribution.
-#
-# * Neither the name of the California Institute of Technology nor
-# the names of its contributors may be used to endorse or promote
-# products derived from this software without specific prior
-# written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#
-
-
-from cig.seismo.events import CMTSolution
-from opal import forms
-from opal.http import HttpResponseRedirect
-from opal.shortcuts import render_to_response
-from opal.template.context import RequestContext
-from HTMLParser import HTMLParser
-from models import DataSource, Region
-
-
-def search(request):
- import urllib2
-
- if request.method == 'GET':
- return render_to_response('events/event_search.html',
- {},
- RequestContext(request, {}))
-
- # Simply forward the search request to Harvard.
- query = request.POST.urlencode()
- url = "http://www.seismology.harvard.edu/cgi-bin/CMT3/form?" + query
- src = urllib2.urlopen(url)
-
- # Parse the results.
- parser = HarvardCMTSearchResultsParser()
- parser.feed(src.read())
-
- parser.close()
- src.close()
-
- # Make sure secondary objects exist in the database.
- for event in parser.cmtList:
- # The try-get()-except shouldn't be necessary, but simply
- # using save() causes Django to die in the database backend.
- try:
- ds = DataSource.objects.get(name=event.dataSource)
- except DataSource.DoesNotExist:
- ds = DataSource(event.dataSource)
- ds.save()
- try:
- ds = Region.objects.get(name=event.regionName)
- except:
- r = Region(event.regionName)
- r.save()
-
- return render_to_response('events/event_search_results.html',
- {'event_list': parser.cmtList },
- RequestContext(request, {}))
-
-
-def add(request):
- from forms import AddSingleSourceEventManipulator
- from os.path import dirname
-
- manipulator = AddSingleSourceEventManipulator()
-
- if request.method == 'POST':
- new_data = request.POST.copy()
- errors = manipulator.get_validation_errors(new_data)
- if not errors:
- manipulator.do_html2python(new_data)
- new_event = manipulator.save(new_data, request.user)
- url = "%s/%i/" % (dirname(dirname(request.path)), new_event.id)
- return HttpResponseRedirect(url)
- else:
- errors = new_data = {}
-
- form = forms.FormWrapper(manipulator, new_data, errors)
- return render_to_response('events/single_source_event_form.html',
- {'form': form},
- RequestContext(request, {}))
-
-
-def upload(request):
- from forms import UploadEventManipulator
- from os.path import dirname
-
- manipulator = UploadEventManipulator()
-
- if request.method == 'POST':
- new_data = request.POST.copy()
- new_data.update(request.FILES)
- errors = manipulator.get_validation_errors(new_data)
- if not errors:
- manipulator.do_html2python(new_data)
- new_event = manipulator.save(new_data, request.user)
- url = "%s/%i/" % (dirname(dirname(request.path)), new_event.id)
- return HttpResponseRedirect(url)
- else:
- errors = new_data = {}
-
- form = forms.FormWrapper(manipulator, new_data, errors)
- return render_to_response('events/event_upload.html',
- {'form': form},
- RequestContext(request, {}))
-
-
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# support code
-
-
-class HarvardCMTSearchResultsParser(HTMLParser):
-
- def __init__(self):
- HTMLParser.__init__(self)
- self.state = 0
- self.cmtList = None
-
- def handle_starttag(self, tag, attrs):
- if self.state == 0:
- if tag == 'body':
- self.state = 1
- elif self.state == 2:
- if tag == 'pre':
- self.state = 3
- return
-
- def handle_endtag(self, tag):
- if tag == 'body':
- self.state = 0
- elif self.state == 3:
- if tag == 'pre':
- self.state = 1
- return
-
- def handle_data(self, data):
- if self.state == 1:
- if data.find('Output in CMTSOLUTION format') != -1:
- self.state = 2
- elif self.state == 3:
- self.cmtList = CMTSolution.parse(data)
- return
-
-
-# end of file
Modified: cs/pythia/trunk/opal/components/WebComponent.py
===================================================================
--- cs/pythia/trunk/opal/components/WebComponent.py 2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/opal/components/WebComponent.py 2007-08-08 03:37:43 UTC (rev 7784)
@@ -12,16 +12,103 @@
from pyre.components import Component
+import opal.views as views
+import opal.controllers as controllers
+from opal.template import Context, RequestContext, loader
+from opal import http
class WebComponent(Component):
- children = {}
+ models = []
+ urlpatterns = []
- def view(self):
- return self.DefaultViewClass(self)
+ # urlpatterns support
+ include = lambda urlconf_module: [urlconf_module]
+ def patterns(self, *tuples):
+ from opal.core.urlresolvers import RegexURLPattern, RegexURLResolver
+ pattern_list = []
+ for t in tuples:
+ regex, view_or_include = t[:2]
+ default_kwargs = t[2:]
+ if type(view_or_include) == list:
+ include = view_or_include[0]
+ pattern_list.append(RegexURLResolver(regex, include, *default_kwargs))
+ else:
+ view = view_or_include
+ pattern_list.append(RegexURLPattern(regex, view, *default_kwargs))
+ return pattern_list
+
+
+ # generic views
+
+ def genericObjectList(request, **kwds):
+ view = views.ListView(**kwds)
+ return view.response(request)
+
+
+ def genericObjectDetail(request, **kwds):
+ view = views.DetailView(**kwds)
+ return view.response(request)
+
+
+ # generic views -- CRUD
+
+ def genericCreateObject(request, post_save_redirect=None, follow=None, **kwds):
+ controller = controllers.CreationController(
+ post_redirect = post_save_redirect,
+ follow = follow,
+ )
+ view = views.DetailView(controller = controller, **kwds)
+ return view.response(request)
+
+
+ def genericUpdateObject(request, post_save_redirect=None, follow=None, **kwds):
+ controller = controllers.UpdateController(
+ post_redirect = post_save_redirect,
+ follow = follow,
+ )
+ view = views.DetailView(controller = controller, **kwds)
+ return view.response(request)
+
+
+ def genericDeleteObject(request, post_delete_redirect, **kwds):
+ controller = controllers.DeletionController(
+ post_redirect = post_delete_redirect,
+ )
+ view = views.DetailView(controller = controller, **kwds)
+ return view.response(request)
+
+
+ # errors
+
+ def handler404(request, template_name='404.html'):
+ """
+ Default 404 handler, which looks for the requested URL in the redirects
+ table, redirects if found, and displays 404 page if not redirected.
+
+ Templates: `404.html`
+ Context:
+ request_path
+ The path of the requested URL (e.g., '/app/pages/bad_page/')
+ """
+ t = loader.get_template(template_name) # You need to create a 404.html template.
+ return http.HttpResponseNotFound(t.render(RequestContext(request, {'request_path': request.path})))
+
+
+ def handler500(request, template_name='500.html'):
+ """
+ 500 error handler.
+
+ Templates: `500.html`
+ Context: None
+ """
+ t = loader.get_template(template_name) # You need to create a 500.html template.
+ return http.HttpResponseServerError(t.render(Context({})))
+
+
# end of file
Modified: cs/pythia/trunk/opal/components/__init__.py
===================================================================
--- cs/pythia/trunk/opal/components/__init__.py 2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/opal/components/__init__.py 2007-08-08 03:37:43 UTC (rev 7784)
@@ -12,6 +12,9 @@
#
+from WebComponent import WebComponent
+
+
def actor(name):
from GenericActor import GenericActor
return GenericActor(name)
Deleted: cs/pythia/trunk/opal/conf/urls/defaults.py
===================================================================
--- cs/pythia/trunk/opal/conf/urls/defaults.py 2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/opal/conf/urls/defaults.py 2007-08-08 03:37:43 UTC (rev 7784)
@@ -1,19 +0,0 @@
-from opal.core.urlresolvers import RegexURLPattern, RegexURLResolver
-
-__all__ = ['handler404', 'handler500', 'include', 'patterns']
-
-handler404 = 'opal.views.defaults.page_not_found'
-handler500 = 'opal.views.defaults.server_error'
-
-include = lambda urlconf_module: [urlconf_module]
-
-def patterns(prefix, *tuples):
- pattern_list = []
- for t in tuples:
- regex, view_or_include = t[:2]
- default_kwargs = t[2:]
- if type(view_or_include) == list:
- pattern_list.append(RegexURLResolver(regex, view_or_include[0], *default_kwargs))
- else:
- pattern_list.append(RegexURLPattern(regex, prefix and (prefix + '.' + view_or_include) or view_or_include, *default_kwargs))
- return pattern_list
Modified: cs/pythia/trunk/opal/core/handlers/base.py
===================================================================
--- cs/pythia/trunk/opal/core/handlers/base.py 2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/opal/core/handlers/base.py 2007-08-08 03:37:43 UTC (rev 7784)
@@ -60,9 +60,10 @@
if response:
return response
+ site = settings
+ resolver = site.resolve
try:
- site = settings
- callback, callback_args, callback_kwargs = site.resolve(request.path)
+ callback, callback_args, callback_kwargs = resolver.resolve(path)
# Apply view middleware
for middleware_method in self._view_middleware:
Modified: cs/pythia/trunk/opal/db/queries.py
===================================================================
--- cs/pythia/trunk/opal/db/queries.py 2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/opal/db/queries.py 2007-08-08 03:37:43 UTC (rev 7784)
@@ -13,49 +13,32 @@
class Query(object):
+ def __init__(self, fieldName, key):
+ self.fieldName = fieldName
+ self.key = key
+
def apply(self, queryset):
- raise NotImplementedError()
+ return queryset.filter(**{self.fieldName: self.key})
def get(self, queryset):
queryset = self.apply(queryset)
return queryset.get()
-
-class ObjectIdQuery(Query):
-
- def __init__(self, object_id):
- Query.__init__(self)
- self.object_id = object_id
-
- def apply(self, queryset):
- return queryset.filter(pk=self.object_id)
-
def __str__(self):
- return "object_id=%s" % self.object_id
+ return "%s='%s'" % (self.fieldName, self.key)
-class ObjectSlugQuery(Query):
- def __init__(self, slug, slug_field):
- Query.__init__(self)
- self.slug = slug
- self.slug_field = slug_field
+class Inquirer(object):
+
+ def newQuery(self, key):
+ return self.Query(fieldName, key)
- def apply(self, queryset):
- return queryset.filter(**{self.slug_field: self.slug})
+ def __init__(self, fieldName):
+ self.fieldName = fieldName
- def __str__(self):
- return "%s='%s'" % (self.slug_field, self.slug)
+primaryInquirer = Inquirer('pk')
-def objectQuery(object_id=None, slug=None, slug_field=None):
- if object_id:
- query = ObjectIdQuery(object_id)
- elif slug and slug_field:
- query = ObjectSlugQuery(slug, slug_field)
- else:
- raise AttributeError, "Object query must be created with either an object_id or a slug/slug_field."
- return query
-
# end of file
Modified: cs/pythia/trunk/opal/views/defaults.py
===================================================================
--- cs/pythia/trunk/opal/views/defaults.py 2007-08-08 03:07:52 UTC (rev 7783)
+++ cs/pythia/trunk/opal/views/defaults.py 2007-08-08 03:37:43 UTC (rev 7784)
@@ -1,5 +1,4 @@
from opal.core.exceptions import ObjectDoesNotExist
-from opal.template import Context, RequestContext, loader
from opal.contrib.contenttypes.models import ContentType
from opal.contrib.sites.models import Site
from opal import http
@@ -65,25 +64,3 @@
else:
return http.HttpResponseRedirect(absurl)
-def page_not_found(request, template_name='404.html'):
- """
- Default 404 handler, which looks for the requested URL in the redirects
- table, redirects if found, and displays 404 page if not redirected.
-
- Templates: `404.html`
- Context:
- request_path
- The path of the requested URL (e.g., '/app/pages/bad_page/')
- """
- t = loader.get_template(template_name) # You need to create a 404.html template.
- return http.HttpResponseNotFound(t.render(RequestContext(request, {'request_path': request.path})))
-
-def server_error(request, template_name='500.html'):
- """
- 500 error handler.
-
- Templates: `500.html`
- Context: None
- """
- t = loader.get_template(template_name) # You need to create a 500.html template.
- return http.HttpResponseServerError(t.render(Context({})))
More information about the cig-commits
mailing list